am d4b688cf: am d165f365: am 5d2d911a: am d1eeb674: Merge "Telephony: Modify code to check that PUK code length is always 8."
* commit 'd4b688cf97736eb4c543149686ab851b9ea21161':
Telephony: Modify code to check that PUK code length is always 8.
diff --git a/Android.mk b/Android.mk
index 3a3169c..ade5e38 100644
--- a/Android.mk
+++ b/Android.mk
@@ -59,6 +59,8 @@
core/java/android/accounts/IAccountManagerResponse.aidl \
core/java/android/accounts/IAccountAuthenticator.aidl \
core/java/android/accounts/IAccountAuthenticatorResponse.aidl \
+ core/java/android/app/IActivityContainer.aidl \
+ core/java/android/app/IActivityContainerCallback.aidl \
core/java/android/app/IActivityController.aidl \
core/java/android/app/IActivityPendingResult.aidl \
core/java/android/app/IAlarmManager.aidl \
diff --git a/CleanSpec.mk b/CleanSpec.mk
index cfa8be9..ef3f4ae 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -184,7 +184,7 @@
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/media/audio/effects/)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/framework-res_intermediates)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/print/IPrintClient.*)
-
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/services_intermediates)
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
# ************************************************
diff --git a/api/current.txt b/api/current.txt
index 50337c0..73fb2ec 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3080,6 +3080,14 @@
method public void update(android.app.ActivityOptions);
}
+ public class ActivityView extends android.view.ViewGroup {
+ ctor public ActivityView(android.content.Context);
+ ctor public ActivityView(android.content.Context, android.util.AttributeSet);
+ ctor public ActivityView(android.content.Context, android.util.AttributeSet, int);
+ method protected void onLayout(boolean, int, int, int, int);
+ method public void startActivity(android.content.Intent);
+ }
+
public class AlarmManager {
method public void cancel(android.app.PendingIntent);
method public void set(int, long, android.app.PendingIntent);
@@ -10870,6 +10878,7 @@
method public void registerDisplayListener(android.hardware.display.DisplayManager.DisplayListener, android.os.Handler);
method public void unregisterDisplayListener(android.hardware.display.DisplayManager.DisplayListener);
field public static final java.lang.String DISPLAY_CATEGORY_PRESENTATION = "android.hardware.display.category.PRESENTATION";
+ field public static final int VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY = 8; // 0x8
field public static final int VIRTUAL_DISPLAY_FLAG_PRESENTATION = 2; // 0x2
field public static final int VIRTUAL_DISPLAY_FLAG_PUBLIC = 1; // 0x1
field public static final int VIRTUAL_DISPLAY_FLAG_SECURE = 4; // 0x4
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 0344d26..89e15d2 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -19,8 +19,9 @@
package com.android.commands.am;
import android.app.ActivityManager;
-import android.app.ActivityManager.StackBoxInfo;
+import android.app.ActivityManager.StackInfo;
import android.app.ActivityManagerNative;
+import android.app.IActivityContainer;
import android.app.IActivityController;
import android.app.IActivityManager;
import android.app.IInstrumentationWatcher;
@@ -31,9 +32,11 @@
import android.content.Intent;
import android.content.pm.IPackageManager;
import android.content.pm.ResolveInfo;
+import android.graphics.Rect;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
+import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -106,11 +109,11 @@
" am to-intent-uri [INTENT]\n" +
" am switch-user <USER_ID>\n" +
" am stop-user <USER_ID>\n" +
- " am stack create <TASK_ID> <RELATIVE_STACK_BOX_ID> <POSITION> <WEIGHT>\n" +
+ " am stack start <DISPLAY_ID> <INTENT>\n" +
" am stack movetask <TASK_ID> <STACK_ID> [true|false]\n" +
- " am stack resize <STACK_ID> <WEIGHT>\n" +
- " am stack boxes\n" +
- " am stack box <STACK_BOX_ID>\n" +
+ " am stack resize <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>\n" +
+ " am stack list\n" +
+ " am stack info <STACK_ID>\n" +
"\n" +
"am start: start an Activity. Options are:\n" +
" -D: enable debugging\n" +
@@ -204,24 +207,16 @@
"am stop-user: stop execution of USER_ID, not allowing it to run any\n" +
" code until a later explicit switch to it.\n" +
"\n" +
- "am stack create: create a new stack relative to an existing one.\n" +
- " <TASK_ID>: the task to populate the new stack with. Must exist.\n" +
- " <RELATIVE_STACK_BOX_ID>: existing stack box's id.\n" +
- " <POSITION>: 0: before <RELATIVE_STACK_BOX_ID>, per RTL/LTR configuration,\n" +
- " 1: after <RELATIVE_STACK_BOX_ID>, per RTL/LTR configuration,\n" +
- " 2: to left of <RELATIVE_STACK_BOX_ID>,\n" +
- " 3: to right of <RELATIVE_STACK_BOX_ID>," +
- " 4: above <RELATIVE_STACK_BOX_ID>, 5: below <RELATIVE_STACK_BOX_ID>\n" +
- " <WEIGHT>: float between 0.2 and 0.8 inclusive.\n" +
+ "am stack start: start a new activity on <DISPLAY_ID> using <INTENT>.\n" +
"\n" +
"am stack movetask: move <TASK_ID> from its current stack to the top (true) or" +
" bottom (false) of <STACK_ID>.\n" +
"\n" +
- "am stack resize: change <STACK_ID> relative size to new <WEIGHT>.\n" +
+ "am stack resize: change <STACK_ID> size and position to <LEFT,TOP,RIGHT,BOTTOM>.\n" +
"\n" +
- "am stack boxes: list the hierarchy of stack boxes and their contents.\n" +
+ "am stack list: list all of the activity stacks and their sizes.\n" +
"\n" +
- "am stack box: list the hierarchy of stack boxes rooted at <STACK_BOX_ID>.\n" +
+ "am stack info: display the information about activity stack <STACK_ID>.\n" +
"\n" +
"<INTENT> specifications include these flags and arguments:\n" +
" [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]\n" +
@@ -1546,35 +1541,32 @@
private void runStack() throws Exception {
String op = nextArgRequired();
- if (op.equals("create")) {
- runStackCreate();
+ if (op.equals("start")) {
+ runStackStart();
} else if (op.equals("movetask")) {
runStackMoveTask();
} else if (op.equals("resize")) {
- runStackBoxResize();
- } else if (op.equals("boxes")) {
- runStackBoxes();
- } else if (op.equals("box")) {
- runStackBoxInfo();
+ runStackResize();
+ } else if (op.equals("list")) {
+ runStackList();
+ } else if (op.equals("info")) {
+ runStackInfo();
} else {
showError("Error: unknown command '" + op + "'");
return;
}
}
- private void runStackCreate() throws Exception {
- String taskIdStr = nextArgRequired();
- int taskId = Integer.valueOf(taskIdStr);
- String relativeToStr = nextArgRequired();
- int relativeTo = Integer.valueOf(relativeToStr);
- String positionStr = nextArgRequired();
- int position = Integer.valueOf(positionStr);
- String weightStr = nextArgRequired();
- float weight = Float.valueOf(weightStr);
+ private void runStackStart() throws Exception {
+ String displayIdStr = nextArgRequired();
+ int displayId = Integer.valueOf(displayIdStr);
+ Intent intent = makeIntent(UserHandle.USER_CURRENT);
try {
- int stackId = mAm.createStack(taskId, relativeTo, position, weight);
- System.out.println("createStack returned new stackId=" + stackId + "\n\n");
+ IBinder homeActivityToken = mAm.getHomeActivityToken();
+ IActivityContainer container = mAm.createActivityContainer(homeActivityToken, null);
+ container.attachToDisplay(displayId);
+ container.startActivity(intent);
} catch (RemoteException e) {
}
}
@@ -1601,34 +1593,40 @@
}
}
- private void runStackBoxResize() throws Exception {
- String stackBoxIdStr = nextArgRequired();
- int stackBoxId = Integer.valueOf(stackBoxIdStr);
- String weightStr = nextArgRequired();
- float weight = Float.valueOf(weightStr);
+ private void runStackResize() throws Exception {
+ String stackIdStr = nextArgRequired();
+ int stackId = Integer.valueOf(stackIdStr);
+ String leftStr = nextArgRequired();
+ int left = Integer.valueOf(leftStr);
+ String topStr = nextArgRequired();
+ int top = Integer.valueOf(topStr);
+ String rightStr = nextArgRequired();
+ int right = Integer.valueOf(rightStr);
+ String bottomStr = nextArgRequired();
+ int bottom = Integer.valueOf(bottomStr);
try {
- mAm.resizeStackBox(stackBoxId, weight);
+ mAm.resizeStack(stackId, new Rect(left, top, right, bottom));
} catch (RemoteException e) {
}
}
- private void runStackBoxes() throws Exception {
+ private void runStackList() throws Exception {
try {
- List<StackBoxInfo> stackBoxes = mAm.getStackBoxes();
- for (StackBoxInfo info : stackBoxes) {
+ List<StackInfo> stacks = mAm.getAllStackInfos();
+ for (StackInfo info : stacks) {
System.out.println(info);
}
} catch (RemoteException e) {
}
}
- private void runStackBoxInfo() throws Exception {
+ private void runStackInfo() throws Exception {
try {
- String stackBoxIdStr = nextArgRequired();
- int stackBoxId = Integer.valueOf(stackBoxIdStr);
- StackBoxInfo stackBoxInfo = mAm.getStackBoxInfo(stackBoxId);
- System.out.println(stackBoxInfo);
+ String stackIdStr = nextArgRequired();
+ int stackId = Integer.valueOf(stackIdStr);
+ StackInfo info = mAm.getStackInfo(stackId);
+ System.out.println(info);
} catch (RemoteException e) {
}
}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 7ca3459..c877cd3 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -1289,106 +1289,15 @@
}
/**
- * Information you can retrieve about the WindowManager StackBox hierarchy.
- * @hide
- */
- public static class StackBoxInfo implements Parcelable {
- public int stackBoxId;
- public float weight;
- public boolean vertical;
- public Rect bounds;
- public StackBoxInfo[] children;
- public int stackId;
- public StackInfo stack;
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(stackBoxId);
- dest.writeFloat(weight);
- dest.writeInt(vertical ? 1 : 0);
- bounds.writeToParcel(dest, flags);
- dest.writeInt(stackId);
- if (children != null) {
- children[0].writeToParcel(dest, flags);
- children[1].writeToParcel(dest, flags);
- } else {
- stack.writeToParcel(dest, flags);
- }
- }
-
- public void readFromParcel(Parcel source) {
- stackBoxId = source.readInt();
- weight = source.readFloat();
- vertical = source.readInt() == 1;
- bounds = Rect.CREATOR.createFromParcel(source);
- stackId = source.readInt();
- if (stackId == -1) {
- children = new StackBoxInfo[2];
- children[0] = StackBoxInfo.CREATOR.createFromParcel(source);
- children[1] = StackBoxInfo.CREATOR.createFromParcel(source);
- } else {
- stack = StackInfo.CREATOR.createFromParcel(source);
- }
- }
-
- public static final Creator<StackBoxInfo> CREATOR =
- new Creator<ActivityManager.StackBoxInfo>() {
-
- @Override
- public StackBoxInfo createFromParcel(Parcel source) {
- return new StackBoxInfo(source);
- }
-
- @Override
- public StackBoxInfo[] newArray(int size) {
- return new StackBoxInfo[size];
- }
- };
-
- public StackBoxInfo() {
- }
-
- public StackBoxInfo(Parcel source) {
- readFromParcel(source);
- }
-
- public String toString(String prefix) {
- StringBuilder sb = new StringBuilder(256);
- sb.append(prefix); sb.append("Box id=" + stackBoxId); sb.append(" weight=" + weight);
- sb.append(" vertical=" + vertical); sb.append(" bounds=" + bounds.toShortString());
- sb.append("\n");
- if (children != null) {
- sb.append(prefix); sb.append("First child=\n");
- sb.append(children[0].toString(prefix + " "));
- sb.append(prefix); sb.append("Second child=\n");
- sb.append(children[1].toString(prefix + " "));
- } else {
- sb.append(prefix); sb.append("Stack=\n");
- sb.append(stack.toString(prefix + " "));
- }
- return sb.toString();
- }
-
- @Override
- public String toString() {
- return toString("");
- }
- }
-
- /**
* Information you can retrieve about an ActivityStack in the system.
* @hide
*/
public static class StackInfo implements Parcelable {
public int stackId;
- public Rect bounds;
+ public Rect bounds = new Rect();
public int[] taskIds;
public String[] taskNames;
+ public int displayId;
@Override
public int describeContents() {
@@ -1404,6 +1313,7 @@
dest.writeInt(bounds.bottom);
dest.writeIntArray(taskIds);
dest.writeStringArray(taskNames);
+ dest.writeInt(displayId);
}
public void readFromParcel(Parcel source) {
@@ -1412,6 +1322,7 @@
source.readInt(), source.readInt(), source.readInt(), source.readInt());
taskIds = source.createIntArray();
taskNames = source.createStringArray();
+ displayId = source.readInt();
}
public static final Creator<StackInfo> CREATOR = new Creator<StackInfo>() {
@@ -1435,7 +1346,9 @@
public String toString(String prefix) {
StringBuilder sb = new StringBuilder(256);
sb.append(prefix); sb.append("Stack id="); sb.append(stackId);
- sb.append(" bounds="); sb.append(bounds.toShortString()); sb.append("\n");
+ sb.append(" bounds="); sb.append(bounds.toShortString());
+ sb.append(" displayId="); sb.append(displayId);
+ sb.append("\n");
prefix = prefix + " ";
for (int i = 0; i < taskIds.length; ++i) {
sb.append(prefix); sb.append("taskId="); sb.append(taskIds[i]);
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 74266cc..7b81713 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -16,7 +16,7 @@
package android.app;
-import android.app.ActivityManager.StackBoxInfo;
+import android.app.ActivityManager.StackInfo;
import android.content.ComponentName;
import android.content.IIntentReceiver;
import android.content.IIntentSender;
@@ -31,6 +31,7 @@
import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
+import android.graphics.Rect;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
@@ -611,18 +612,6 @@
return true;
}
- case CREATE_STACK_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- int taskId = data.readInt();
- int relativeStackId = data.readInt();
- int position = data.readInt();
- float weight = data.readFloat();
- int res = createStack(taskId, relativeStackId, position, weight);
- reply.writeNoException();
- reply.writeInt(res);
- return true;
- }
-
case MOVE_TASK_TO_STACK_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
int taskId = data.readInt();
@@ -635,25 +624,26 @@
case RESIZE_STACK_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
- int stackBoxId = data.readInt();
+ int stackId = data.readInt();
float weight = data.readFloat();
- resizeStackBox(stackBoxId, weight);
+ Rect r = Rect.CREATOR.createFromParcel(data);
+ resizeStack(stackId, r);
reply.writeNoException();
return true;
}
- case GET_STACK_BOXES_TRANSACTION: {
+ case GET_ALL_STACK_INFOS_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
- List<StackBoxInfo> list = getStackBoxes();
+ List<StackInfo> list = getAllStackInfos();
reply.writeNoException();
reply.writeTypedList(list);
return true;
}
- case GET_STACK_BOX_INFO_TRANSACTION: {
+ case GET_STACK_INFO_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
- int stackBoxId = data.readInt();
- StackBoxInfo info = getStackBoxInfo(stackBoxId);
+ int stackId = data.readInt();
+ StackInfo info = getStackInfo(stackId);
reply.writeNoException();
if (info != null) {
reply.writeInt(1);
@@ -2028,6 +2018,45 @@
reply.writeNoException();
return true;
}
+
+ case CREATE_ACTIVITY_CONTAINER_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ IBinder parentActivityToken = data.readStrongBinder();
+ IActivityContainerCallback callback =
+ (IActivityContainerCallback) data.readStrongBinder();
+ IActivityContainer activityContainer =
+ createActivityContainer(parentActivityToken, callback);
+ reply.writeNoException();
+ if (activityContainer != null) {
+ reply.writeInt(1);
+ reply.writeStrongBinder(activityContainer.asBinder());
+ } else {
+ reply.writeInt(0);
+ }
+ return true;
+ }
+
+ case GET_ACTIVITY_CONTAINER_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ IBinder activityToken = data.readStrongBinder();
+ IActivityContainer activityContainer = getEnclosingActivityContainer(activityToken);
+ reply.writeNoException();
+ if (activityContainer != null) {
+ reply.writeInt(1);
+ reply.writeStrongBinder(activityContainer.asBinder());
+ } else {
+ reply.writeInt(0);
+ }
+ return true;
+ }
+
+ case GET_HOME_ACTIVITY_TOKEN_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ IBinder homeActivityToken = getHomeActivityToken();
+ reply.writeNoException();
+ reply.writeStrongBinder(homeActivityToken);
+ return true;
+ }
}
return super.onTransact(code, data, reply, flags);
@@ -2715,24 +2744,6 @@
reply.recycle();
}
@Override
- public int createStack(int taskId, int relativeStackBoxId, int position, float weight)
- throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeInt(taskId);
- data.writeInt(relativeStackBoxId);
- data.writeInt(position);
- data.writeFloat(weight);
- mRemote.transact(CREATE_STACK_TRANSACTION, data, reply, 0);
- reply.readException();
- int res = reply.readInt();
- data.recycle();
- reply.recycle();
- return res;
- }
- @Override
public void moveTaskToStack(int taskId, int stackId, boolean toTop) throws RemoteException
{
Parcel data = Parcel.obtain();
@@ -2747,44 +2758,44 @@
reply.recycle();
}
@Override
- public void resizeStackBox(int stackBoxId, float weight) throws RemoteException
+ public void resizeStack(int stackBoxId, Rect r) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeInt(stackBoxId);
- data.writeFloat(weight);
+ r.writeToParcel(data, 0);
mRemote.transact(RESIZE_STACK_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
reply.readException();
data.recycle();
reply.recycle();
}
@Override
- public List<StackBoxInfo> getStackBoxes() throws RemoteException
+ public List<StackInfo> getAllStackInfos() throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
- mRemote.transact(GET_STACK_BOXES_TRANSACTION, data, reply, 0);
+ mRemote.transact(GET_ALL_STACK_INFOS_TRANSACTION, data, reply, 0);
reply.readException();
- ArrayList<StackBoxInfo> list = reply.createTypedArrayList(StackBoxInfo.CREATOR);
+ ArrayList<StackInfo> list = reply.createTypedArrayList(StackInfo.CREATOR);
data.recycle();
reply.recycle();
return list;
}
@Override
- public StackBoxInfo getStackBoxInfo(int stackBoxId) throws RemoteException
+ public StackInfo getStackInfo(int stackId) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeInt(stackBoxId);
- mRemote.transact(GET_STACK_BOX_INFO_TRANSACTION, data, reply, 0);
+ data.writeInt(stackId);
+ mRemote.transact(GET_STACK_INFO_TRANSACTION, data, reply, 0);
reply.readException();
int res = reply.readInt();
- StackBoxInfo info = null;
+ StackInfo info = null;
if (res != 0) {
- info = StackBoxInfo.CREATOR.createFromParcel(reply);
+ info = StackInfo.CREATOR.createFromParcel(reply);
}
data.recycle();
reply.recycle();
@@ -4660,5 +4671,58 @@
reply.recycle();
}
+ public IActivityContainer createActivityContainer(IBinder parentActivityToken,
+ IActivityContainerCallback callback) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeStrongBinder(parentActivityToken);
+ data.writeStrongBinder((IBinder)callback);
+ mRemote.transact(CREATE_ACTIVITY_CONTAINER_TRANSACTION, data, reply, 0);
+ reply.readException();
+ final int result = reply.readInt();
+ final IActivityContainer res;
+ if (result == 1) {
+ res = IActivityContainer.Stub.asInterface(reply.readStrongBinder());
+ } else {
+ res = null;
+ }
+ data.recycle();
+ reply.recycle();
+ return res;
+ }
+
+ public IActivityContainer getEnclosingActivityContainer(IBinder activityToken)
+ throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeStrongBinder(activityToken);
+ mRemote.transact(GET_ACTIVITY_CONTAINER_TRANSACTION, data, reply, 0);
+ reply.readException();
+ final int result = reply.readInt();
+ final IActivityContainer res;
+ if (result == 1) {
+ res = IActivityContainer.Stub.asInterface(reply.readStrongBinder());
+ } else {
+ res = null;
+ }
+ data.recycle();
+ reply.recycle();
+ return res;
+ }
+
+ public IBinder getHomeActivityToken() throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ mRemote.transact(GET_HOME_ACTIVITY_TOKEN_TRANSACTION, data, reply, 0);
+ reply.readException();
+ IBinder res = reply.readStrongBinder();
+ data.recycle();
+ reply.recycle();
+ return res;
+ }
+
private IBinder mRemote;
}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 97baf9a..9f21a36 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -2219,15 +2219,27 @@
ContextImpl appContext = new ContextImpl();
appContext.init(r.packageInfo, r.token, this);
appContext.setOuterContext(activity);
+ Context baseContext = appContext;
+
+ final DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
+ try {
+ IActivityContainer container =
+ ActivityManagerNative.getDefault().getEnclosingActivityContainer(r.token);
+ final int displayId =
+ container == null ? Display.DEFAULT_DISPLAY : container.getDisplayId();
+ if (displayId > Display.DEFAULT_DISPLAY) {
+ Display display = dm.getRealDisplay(displayId, r.token);
+ baseContext = appContext.createDisplayContext(display);
+ }
+ } catch (RemoteException e) {
+ }
// For debugging purposes, if the activity's package name contains the value of
// the "debug.use-second-display" system property as a substring, then show
// its content on a secondary display if there is one.
- Context baseContext = appContext;
String pkgName = SystemProperties.get("debug.second-display.pkg");
if (pkgName != null && !pkgName.isEmpty()
&& r.packageInfo.mPackageName.contains(pkgName)) {
- DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
for (int displayId : dm.getDisplayIds()) {
if (displayId != Display.DEFAULT_DISPLAY) {
Display display = dm.getRealDisplay(displayId, r.token);
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
new file mode 100644
index 0000000..25cde8c
--- /dev/null
+++ b/core/java/android/app/ActivityView.java
@@ -0,0 +1,180 @@
+/*
+ * 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.app;
+
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.Intent;
+import android.graphics.SurfaceTexture;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.Surface;
+import android.view.TextureView;
+import android.view.TextureView.SurfaceTextureListener;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+
+public class ActivityView extends ViewGroup {
+ private final String TAG = "ActivityView";
+
+ private final TextureView mTextureView;
+ private IActivityContainer mActivityContainer;
+ private Activity mActivity;
+ private boolean mAttached;
+ private int mWidth;
+ private int mHeight;
+ private Surface mSurface;
+
+ public ActivityView(Context context) {
+ this(context, null);
+ }
+
+ public ActivityView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public ActivityView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+ while (context instanceof ContextWrapper) {
+ if (context instanceof Activity) {
+ mActivity = (Activity)context;
+ break;
+ }
+ context = ((ContextWrapper)context).getBaseContext();
+ }
+ if (mActivity == null) {
+ throw new IllegalStateException("The ActivityView's Context is not an Activity.");
+ }
+
+ mTextureView = new TextureView(context);
+ mTextureView.setSurfaceTextureListener(new ActivityViewSurfaceTextureListener());
+ addView(mTextureView);
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ mTextureView.layout(l, t, r, b);
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ try {
+ final IBinder token = mActivity.getActivityToken();
+ mActivityContainer =
+ ActivityManagerNative.getDefault().createActivityContainer(token, null);
+ } catch (RemoteException e) {
+ throw new IllegalStateException("ActivityView: Unable to create ActivityContainer. "
+ + e);
+ }
+
+ final SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture();
+ if (surfaceTexture != null) {
+ attachToSurface(surfaceTexture);
+ }
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ detachFromSurface();
+ }
+
+ @Override
+ public boolean isAttachedToWindow() {
+ return mAttached;
+ }
+
+ public void startActivity(Intent intent) {
+ if (mActivityContainer != null && mAttached) {
+ try {
+ mActivityContainer.startActivity(intent);
+ } catch (RemoteException e) {
+ throw new IllegalStateException("ActivityView: Unable to startActivity. " + e);
+ }
+ }
+ }
+
+ /** Call when both mActivityContainer and mTextureView's SurfaceTexture are not null */
+ private void attachToSurface(SurfaceTexture surfaceTexture) {
+ 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);
+ } catch (RemoteException e) {
+ mActivityContainer = null;
+ mSurface.release();
+ mSurface = null;
+ mAttached = false;
+ throw new IllegalStateException(
+ "ActivityView: Unable to create ActivityContainer. " + e);
+ }
+ mAttached = true;
+ }
+
+ private void detachFromSurface() {
+ if (mActivityContainer != null) {
+ try {
+ mActivityContainer.detachFromDisplay();
+ } catch (RemoteException e) {
+ }
+ mActivityContainer = null;
+ }
+ if (mSurface != null) {
+ mSurface.release();
+ mSurface = null;
+ }
+ mAttached = false;
+ }
+
+ private class ActivityViewSurfaceTextureListener implements SurfaceTextureListener {
+ @Override
+ public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width,
+ int height) {
+ mWidth = width;
+ mHeight = height;
+ if (mActivityContainer != null) {
+ attachToSurface(surfaceTexture);
+ }
+ }
+
+ @Override
+ public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width,
+ int height) {
+ Log.d(TAG, "onSurfaceTextureSizeChanged: w=" + width + " h=" + height);
+ }
+
+ @Override
+ public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
+ Log.d(TAG, "onSurfaceTextureDestroyed");
+ detachFromSurface();
+ return true;
+ }
+
+ @Override
+ public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
+// Log.d(TAG, "onSurfaceTextureUpdated");
+ }
+
+ }
+}
diff --git a/core/java/android/app/IActivityContainer.aidl b/core/java/android/app/IActivityContainer.aidl
new file mode 100644
index 0000000..df1cf91
--- /dev/null
+++ b/core/java/android/app/IActivityContainer.aidl
@@ -0,0 +1,31 @@
+/**
+ * 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.app;
+
+import android.app.IActivityContainerCallback;
+import android.content.Intent;
+import android.os.IBinder;
+import android.view.Surface;
+
+/** @hide */
+interface IActivityContainer {
+ void attachToDisplay(int displayId);
+ void attachToSurface(in Surface surface, int width, int height, int density);
+ void detachFromDisplay();
+ int startActivity(in Intent intent);
+ int getDisplayId();
+}
diff --git a/core/java/android/app/IActivityContainerCallback.aidl b/core/java/android/app/IActivityContainerCallback.aidl
new file mode 100644
index 0000000..55c2001
--- /dev/null
+++ b/core/java/android/app/IActivityContainerCallback.aidl
@@ -0,0 +1,24 @@
+/**
+ * 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.app;
+
+import android.os.IBinder;
+
+/** @hide */
+interface IActivityContainerCallback {
+ oneway void onLastActivityRemoved(IBinder container);
+}
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 77c2ea0..3ed3f7b 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -18,7 +18,7 @@
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityManager.RunningServiceInfo;
-import android.app.ActivityManager.StackBoxInfo;
+import android.app.ActivityManager.StackInfo;
import android.content.ComponentName;
import android.content.ContentProviderNative;
import android.content.IContentProvider;
@@ -36,6 +36,7 @@
import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
+import android.graphics.Rect;
import android.net.Uri;
import android.os.Bundle;
import android.os.Debug;
@@ -117,12 +118,10 @@
public void moveTaskToBack(int task) throws RemoteException;
public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) throws RemoteException;
public void moveTaskBackwards(int task) throws RemoteException;
- public int createStack(int taskId, int relativeStackBoxId, int position, float weight)
- throws RemoteException;
public void moveTaskToStack(int taskId, int stackId, boolean toTop) throws RemoteException;
- public void resizeStackBox(int stackBoxId, float weight) throws RemoteException;
- public List<StackBoxInfo> getStackBoxes() throws RemoteException;
- public StackBoxInfo getStackBoxInfo(int stackBoxId) throws RemoteException;
+ public void resizeStack(int stackId, Rect bounds) throws RemoteException;
+ public List<StackInfo> getAllStackInfos() throws RemoteException;
+ public StackInfo getStackInfo(int stackId) throws RemoteException;
public void setFocusedStack(int stackId) throws RemoteException;
public int getTaskForActivity(IBinder token, boolean onlyRoot) throws RemoteException;
/* oneway */
@@ -408,6 +407,14 @@
public void performIdleMaintenance() throws RemoteException;
+ public IActivityContainer createActivityContainer(IBinder parentActivityToken,
+ IActivityContainerCallback callback) throws RemoteException;
+
+ public IActivityContainer getEnclosingActivityContainer(IBinder activityToken)
+ throws RemoteException;
+
+ public IBinder getHomeActivityToken() throws RemoteException;
+
/*
* Private non-Binder interfaces
*/
@@ -678,12 +685,12 @@
int KILL_UID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+164;
int SET_USER_IS_MONKEY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+165;
int HANG_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+166;
- int CREATE_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+167;
+ int CREATE_ACTIVITY_CONTAINER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+167;
int MOVE_TASK_TO_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+168;
int RESIZE_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+169;
- int GET_STACK_BOXES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+170;
+ int GET_ALL_STACK_INFOS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+170;
int SET_FOCUSED_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+171;
- int GET_STACK_BOX_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+172;
+ int GET_STACK_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+172;
int CONVERT_FROM_TRANSLUCENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+173;
int CONVERT_TO_TRANSLUCENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+174;
int NOTIFY_ACTIVITY_DRAWN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+175;
@@ -694,4 +701,6 @@
int RELEASE_PERSISTABLE_URI_PERMISSION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+180;
int GET_PERSISTED_URI_PERMISSIONS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+181;
int APP_NOT_RESPONDING_VIA_PROVIDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+182;
+ int GET_HOME_ACTIVITY_TOKEN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+183;
+ int GET_ACTIVITY_CONTAINER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+184;
}
diff --git a/core/java/android/app/IWallpaperManager.aidl b/core/java/android/app/IWallpaperManager.aidl
index 3efd3c0..181eb63 100644
--- a/core/java/android/app/IWallpaperManager.aidl
+++ b/core/java/android/app/IWallpaperManager.aidl
@@ -71,4 +71,14 @@
* Returns the desired minimum height for the wallpaper.
*/
int getHeightHint();
+
+ /**
+ * Returns the name of the wallpaper. Private API.
+ */
+ String getName();
+
+ /**
+ * Informs the service that wallpaper settings have been restored. Private API.
+ */
+ void settingsRestored();
}
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index e2bc80a..d1f1f2a 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -27,14 +27,14 @@
import android.os.ServiceManager;
import android.util.Log;
import android.util.Pair;
+
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
-import java.util.HashSet;
import java.util.HashMap;
-import java.util.LinkedList;
+import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
@@ -183,6 +183,43 @@
"android.bluetooth.adapter.extra.DISCOVERABLE_DURATION";
/**
+ * Activity Action: Show a system activity to request BLE advertising.<br>
+ * If the device is not doing BLE advertising, this activity will start BLE advertising for the
+ * device, otherwise it will continue BLE advertising using the current
+ * {@link BluetoothAdvScanData}. <br>
+ * Note this activity will also request the user to turn on Bluetooth if it's not currently
+ * enabled.
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_START_ADVERTISING =
+ "android.bluetooth.adapter.action.START_ADVERTISING";
+
+ /**
+ * Activity Action: Stop the current BLE advertising.
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_STOP_ADVERTISING =
+ "android.bluetooth.adapter.action.STOP_ADVERTISING";
+
+ /**
+ * Broadcast Action: Indicate BLE Advertising is started.
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_BLUETOOTH_ADVERTISING_STARTED =
+ "android.bluetooth.adapter.action.ADVERTISING_STARTED";
+
+ /**
+ * Broadcast Action: Indicated BLE Advertising is stopped.
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_BLUETOOTH_ADVERTISING_STOPPED =
+ "android.bluetooth.adapter.action.ADVERTISING_STOPPED";
+
+ /**
* Activity Action: Show a system activity that allows the user to turn on
* Bluetooth.
* <p>This system activity will return once Bluetooth has completed turning
@@ -251,7 +288,6 @@
*/
public static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 23;
-
/**
* Broadcast Action: The local Bluetooth adapter has started the remote
* device discovery process.
@@ -365,6 +401,8 @@
private IBluetooth mService;
private final Map<LeScanCallback, GattCallbackWrapper> mLeScanClients;
+ private BluetoothAdvScanData mBluetoothAdvScanData = null;
+ private GattCallbackWrapper mAdvertisingCallback;
/**
* Get a handle to the default local Bluetooth adapter.
@@ -438,6 +476,97 @@
}
/**
+ * Returns a {@link BluetoothAdvScanData} object representing advertising data.
+ * @hide
+ */
+ public BluetoothAdvScanData getAdvScanData() {
+ try {
+ IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
+ if (iGatt == null) {
+ // BLE is not supported
+ Log.e(TAG, "failed to start, iGatt null");
+ return null;
+ }
+ if (mBluetoothAdvScanData == null) {
+ mBluetoothAdvScanData = new BluetoothAdvScanData(iGatt, BluetoothAdvScanData.AD);
+ }
+ return mBluetoothAdvScanData;
+ } catch (RemoteException e) {
+ Log.e(TAG, "failed to get advScanData, error: " + e);
+ return null;
+ }
+ }
+
+
+ /**
+ * Start BLE advertising using current {@link BluetoothAdvScanData}.
+ * An app should start advertising by requesting
+ * {@link BluetoothAdapter#ACTION_START_ADVERTISING} instead of calling this method directly.
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}
+ *
+ * @return true if BLE avertising succeeds, false otherwise.
+ * @hide
+ */
+ public boolean startAdvertising() {
+ if (getState() != STATE_ON) return false;
+
+ try {
+ IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
+ if (iGatt == null) {
+ // BLE is not supported.
+ return false;
+ }
+ // Restart/reset advertising packets if advertising is in progress.
+ if (isAdvertising()) {
+ // Invalid advertising callback.
+ if (mAdvertisingCallback == null || mAdvertisingCallback.mLeHandle == -1) {
+ Log.e(TAG, "failed to restart advertising, invalid callback");
+ return false;
+ }
+ iGatt.startAdvertising(mAdvertisingCallback.mLeHandle);
+ return true;
+ }
+ UUID uuid = UUID.randomUUID();
+ GattCallbackWrapper wrapper =
+ new GattCallbackWrapper(this, null, null, GattCallbackWrapper.CALLBACK_TYPE_ADV);
+ iGatt.registerClient(new ParcelUuid(uuid), wrapper);
+ mAdvertisingCallback = wrapper;
+ return true;
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ return false;
+ }
+ }
+
+ /**
+ * Stop BLE advertising.
+ * An app should stop advertising by requesting
+ * {@link BluetoothAdapter#ACTION_STOP_ADVERTISING} instead of calling this method directly.
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}
+ * @return true if BLE advertising stops, false otherwise.
+ * @hide
+ */
+ public boolean stopAdvertisting() {
+ try {
+ IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
+ if (iGatt == null) {
+ // BLE is not supported
+ return false;
+ }
+ if (mAdvertisingCallback == null) {
+ // no callback.
+ return false;
+ }
+ mAdvertisingCallback.stopAdvertising();
+ mAdvertisingCallback = null;
+ return true;
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ return false;
+ }
+ }
+
+ /**
* Return true if Bluetooth is currently enabled and ready for use.
* <p>Equivalent to:
* <code>getBluetoothState() == STATE_ON</code>
@@ -849,6 +978,23 @@
}
/**
+ * Returns whether BLE is currently advertising.
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}.
+ *
+ * @hide
+ */
+ public boolean isAdvertising() {
+ if (getState() != STATE_ON) return false;
+ try {
+ IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
+ return iGatt.isAdvertising();
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ }
+ return false;
+ }
+
+ /**
* Return the set of {@link BluetoothDevice} objects that are bonded
* (paired) to the local adapter.
* <p>If Bluetooth state is not {@link #STATE_ON}, this API
@@ -1546,8 +1692,12 @@
private static class GattCallbackWrapper extends IBluetoothGattCallback.Stub {
private static final int LE_CALLBACK_REG_TIMEOUT = 2000;
private static final int LE_CALLBACK_REG_WAIT_COUNT = 5;
+ private static final int CALLBACK_TYPE_SCAN = 0;
+ private static final int CALLBACK_TYPE_ADV = 1;
private final LeScanCallback mLeScanCb;
+ private int mCallbackType;
+
// mLeHandle 0: not registered
// -1: scan stopped
// >0: registered and scan started
@@ -1561,6 +1711,16 @@
mLeScanCb = leScanCb;
mScanFilter = uuid;
mLeHandle = 0;
+ mCallbackType = CALLBACK_TYPE_SCAN;
+ }
+
+ public GattCallbackWrapper(BluetoothAdapter bluetoothAdapter, LeScanCallback leScanCb,
+ UUID[] uuid, int type) {
+ mBluetoothAdapter = new WeakReference<BluetoothAdapter>(bluetoothAdapter);
+ mLeScanCb = leScanCb;
+ mScanFilter = uuid;
+ mLeHandle = 0;
+ mCallbackType = type;
}
public boolean scanStarted() {
@@ -1583,6 +1743,30 @@
return started;
}
+ public void stopAdvertising() {
+ synchronized (this) {
+ if (mLeHandle <= 0) {
+ Log.e(TAG, "Error state, mLeHandle: " + mLeHandle);
+ return;
+ }
+ BluetoothAdapter adapter = mBluetoothAdapter.get();
+ if (adapter != null) {
+ try {
+ IBluetoothGatt iGatt = adapter.getBluetoothManager().getBluetoothGatt();
+ iGatt.stopAdvertising();
+ Log.d(TAG, "unregeistering client " + mLeHandle);
+ iGatt.unregisterClient(mLeHandle);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to stop advertising and unregister" + e);
+ }
+ } else {
+ Log.e(TAG, "stopAdvertising, BluetoothAdapter is null");
+ }
+ mLeHandle = -1;
+ notifyAll();
+ }
+ }
+
public void stopLeScan() {
synchronized(this) {
if (mLeHandle <= 0) {
@@ -1624,14 +1808,18 @@
BluetoothAdapter adapter = mBluetoothAdapter.get();
if (adapter != null) {
iGatt = adapter.getBluetoothManager().getBluetoothGatt();
- if (mScanFilter == null) {
- iGatt.startScan(mLeHandle, false);
+ if (mCallbackType == CALLBACK_TYPE_ADV) {
+ iGatt.startAdvertising(mLeHandle);
} else {
- ParcelUuid[] uuids = new ParcelUuid[mScanFilter.length];
- for(int i = 0; i != uuids.length; ++i) {
- uuids[i] = new ParcelUuid(mScanFilter[i]);
- }
- iGatt.startScanWithUuids(mLeHandle, false, uuids);
+ if (mScanFilter == null) {
+ iGatt.startScan(mLeHandle, false);
+ } else {
+ ParcelUuid[] uuids = new ParcelUuid[mScanFilter.length];
+ for(int i = 0; i != uuids.length; ++i) {
+ uuids[i] = new ParcelUuid(mScanFilter[i]);
+ }
+ iGatt.startScanWithUuids(mLeHandle, false, uuids);
+ }
}
} else {
Log.e(TAG, "onClientRegistered, BluetoothAdapter null");
@@ -1642,7 +1830,7 @@
mLeHandle = -1;
}
if (mLeHandle == -1) {
- // registration succeeded but start scan failed
+ // registration succeeded but start scan or advertise failed
if (iGatt != null) {
try {
iGatt.unregisterClient(mLeHandle);
diff --git a/core/java/android/bluetooth/BluetoothAdvScanData.java b/core/java/android/bluetooth/BluetoothAdvScanData.java
new file mode 100644
index 0000000..a97b0a8
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothAdvScanData.java
@@ -0,0 +1,147 @@
+/*
+ * 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.bluetooth;
+import android.os.ParcelUuid;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.Collections;
+import java.util.List;
+
+
+/**
+ * This class provides the public APIs to set advertising and scan response data when BLE device
+ * operates in peripheral mode. <br>
+ * The exact format is defined in Bluetooth 4.0 specification, Volume 3, Part C, Section 11
+ * @hide
+ */
+public final class BluetoothAdvScanData {
+
+ /**
+ * Available data types of {@link BluetoothAdvScanData}.
+ */
+ public static final int AD = 0; // Advertising Data
+ public static final int SCAN_RESPONSE = 1; // Scan Response
+ public static final int EIR = 2; // Extended Inquiry Response
+
+ private static final String TAG = "BluetoothAdvScanData";
+
+ /**
+ * Data type of BluetoothAdvScanData.
+ */
+ private final int mDataType;
+ /**
+ * Bluetooth Gatt Service.
+ */
+ private IBluetoothGatt mBluetoothGatt;
+
+ /**
+ * @param mBluetoothGatt
+ * @param dataType
+ */
+ public BluetoothAdvScanData(IBluetoothGatt mBluetoothGatt, int dataType) {
+ this.mBluetoothGatt = mBluetoothGatt;
+ this.mDataType = dataType;
+ }
+
+ /**
+ * @return advertising data type.
+ */
+ public int getDataType() {
+ return mDataType;
+ }
+
+ /**
+ * Set manufactureCode and manufactureData.
+ * Returns true if manufacturer data is set, false if there is no enough room to set
+ * manufacturer data or the data is already set.
+ * @param manufacturerCode - unique identifier for the manufacturer
+ * @param manufacturerData - data associated with the specific manufacturer.
+ */
+ public boolean setManufacturerData(int manufacturerCode, byte[] manufacturerData) {
+ if (mDataType != AD) return false;
+ try {
+ return mBluetoothGatt.setAdvManufacturerCodeAndData(manufacturerCode, manufacturerData);
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Set service data. Note the service data can only be set when the data type is {@code AD};
+ * @param serviceData
+ */
+ public boolean setServiceData(byte[] serviceData) {
+
+ if (mDataType != AD) return false;
+ if (serviceData == null) return false;
+ try {
+ return mBluetoothGatt.setAdvServiceData(serviceData);
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Returns an immutable list of service uuids that will be advertised.
+ */
+ public List<ParcelUuid> getServiceUuids() {
+ try {
+ return Collections.unmodifiableList(mBluetoothGatt.getAdvServiceUuids());
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Returns manufacturer data.
+ */
+ public byte[] getManufacturerData() {
+ if (mBluetoothGatt == null) return null;
+ try {
+ return mBluetoothGatt.getAdvManufacturerData();
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Returns service data.
+ */
+ public byte[] getServiceData() {
+ if (mBluetoothGatt == null) return null;
+ try {
+ return mBluetoothGatt.getAdvServiceData();
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Remove manufacturer data based on given manufacturer code.
+ * @param manufacturerCode
+ */
+ public void removeManufacturerCodeAndData(int manufacturerCode) {
+ if (mBluetoothGatt != null) {
+ try {
+ mBluetoothGatt.removeAdvManufacturerCodeAndData(manufacturerCode);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ }
+ }
+}
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index a2bb78c..cd093c5 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -553,14 +553,6 @@
Log.w(TAG, "Unhandled exception in callback", ex);
}
}
-
- /**
- * Listen command status callback
- * @hide
- */
- public void onListen(int status) {
- if (DBG) Log.d(TAG, "onListen() - status=" + status);
- }
};
/*package*/ BluetoothGatt(Context context, IBluetoothGatt iGatt, BluetoothDevice device) {
@@ -693,71 +685,6 @@
return true;
}
- /**
- * Starts or stops sending of advertisement packages to listen for connection
- * requests from a central devices.
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param start Start or stop advertising
- */
- /*package*/ void listen(boolean start) {
- if (mContext == null || !mContext.getResources().
- getBoolean(com.android.internal.R.bool.config_bluetooth_le_peripheral_mode_supported)) {
- throw new UnsupportedOperationException("BluetoothGatt#listen is blocked");
- }
- if (DBG) Log.d(TAG, "listen() - start: " + start);
- if (mService == null || mClientIf == 0) return;
-
- try {
- mService.clientListen(mClientIf, start);
- } catch (RemoteException e) {
- Log.e(TAG,"",e);
- }
- }
-
- /**
- * Sets the advertising data contained in the adv. response packet.
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param advData true to set adv. data, false to set scan response
- * @param includeName Inlucde the name in the adv. response
- * @param includeTxPower Include TX power value
- * @param minInterval Minimum desired scan interval (optional)
- * @param maxInterval Maximum desired scan interval (optional)
- * @param appearance The appearance flags for the device (optional)
- * @param manufacturerData Manufacturer specific data including company ID (optional)
- */
- /*package*/ void setAdvData(boolean advData, boolean includeName, boolean includeTxPower,
- Integer minInterval, Integer maxInterval,
- Integer appearance, Byte[] manufacturerData) {
- if (mContext == null || !mContext.getResources().
- getBoolean(com.android.internal.R.bool.config_bluetooth_le_peripheral_mode_supported)) {
- throw new UnsupportedOperationException("BluetoothGatt#setAdvData is blocked");
- }
- if (DBG) Log.d(TAG, "setAdvData()");
- if (mService == null || mClientIf == 0) return;
-
- byte[] data = new byte[0];
- if (manufacturerData != null) {
- data = new byte[manufacturerData.length];
- for(int i = 0; i != manufacturerData.length; ++i) {
- data[i] = manufacturerData[i];
- }
- }
-
- try {
- mService.setAdvData(mClientIf, !advData,
- includeName, includeTxPower,
- minInterval != null ? minInterval : 0,
- maxInterval != null ? maxInterval : 0,
- appearance != null ? appearance : 0, data);
- } catch (RemoteException e) {
- Log.e(TAG,"",e);
- }
- }
-
/**
* Disconnects an established connection, or cancels a connection attempt
* currently in progress.
diff --git a/core/java/android/bluetooth/BluetoothGattServer.java b/core/java/android/bluetooth/BluetoothGattServer.java
index 58ee54f..153215c 100644
--- a/core/java/android/bluetooth/BluetoothGattServer.java
+++ b/core/java/android/bluetooth/BluetoothGattServer.java
@@ -537,7 +537,7 @@
try {
mService.beginServiceDeclaration(mServerIf, service.getType(),
service.getInstanceId(), service.getHandles(),
- new ParcelUuid(service.getUuid()));
+ new ParcelUuid(service.getUuid()), service.isAdvertisePreferred());
List<BluetoothGattService> includedServices = service.getIncludedServices();
for (BluetoothGattService includedService : includedServices) {
diff --git a/core/java/android/bluetooth/BluetoothGattService.java b/core/java/android/bluetooth/BluetoothGattService.java
index 1e66369..52bc0f7 100644
--- a/core/java/android/bluetooth/BluetoothGattService.java
+++ b/core/java/android/bluetooth/BluetoothGattService.java
@@ -15,8 +15,6 @@
*/
package android.bluetooth;
-import android.bluetooth.BluetoothDevice;
-
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@@ -82,6 +80,11 @@
protected List<BluetoothGattService> mIncludedServices;
/**
+ * Whether the service uuid should be advertised.
+ */
+ private boolean mAdvertisePreferred;
+
+ /**
* Create a new BluetoothGattService.
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
@@ -263,4 +266,20 @@
}
return null;
}
+
+ /**
+ * Returns whether the uuid of the service should be advertised.
+ * @hide
+ */
+ public boolean isAdvertisePreferred() {
+ return mAdvertisePreferred;
+ }
+
+ /**
+ * Set whether the service uuid should be advertised.
+ * @hide
+ */
+ public void setAdvertisePreferred(boolean advertisePreferred) {
+ this.mAdvertisePreferred = advertisePreferred;
+ }
}
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index d10eaea..1e75fc2 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -417,27 +417,28 @@
* if an i/o error occurs.
*/
/*package*/ void flush() throws IOException {
+ if (mSocketOS == null) throw new IOException("flush is called on null OutputStream");
if (VDBG) Log.d(TAG, "flush: " + mSocketOS);
mSocketOS.flush();
}
/*package*/ int read(byte[] b, int offset, int length) throws IOException {
-
- if (VDBG) Log.d(TAG, "read in: " + mSocketIS + " len: " + length);
- int ret = mSocketIS.read(b, offset, length);
- if(ret < 0)
- throw new IOException("bt socket closed, read return: " + ret);
- if (VDBG) Log.d(TAG, "read out: " + mSocketIS + " ret: " + ret);
- return ret;
+ if (mSocketIS == null) throw new IOException("read is called on null InputStream");
+ if (VDBG) Log.d(TAG, "read in: " + mSocketIS + " len: " + length);
+ int ret = mSocketIS.read(b, offset, length);
+ if(ret < 0)
+ throw new IOException("bt socket closed, read return: " + ret);
+ if (VDBG) Log.d(TAG, "read out: " + mSocketIS + " ret: " + ret);
+ return ret;
}
/*package*/ int write(byte[] b, int offset, int length) throws IOException {
-
- if (VDBG) Log.d(TAG, "write: " + mSocketOS + " length: " + length);
- mSocketOS.write(b, offset, length);
- // There is no good way to confirm since the entire process is asynchronous anyway
- if (VDBG) Log.d(TAG, "write out: " + mSocketOS + " length: " + length);
- return length;
+ if (mSocketOS == null) throw new IOException("write is called on null OutputStream");
+ if (VDBG) Log.d(TAG, "write: " + mSocketOS + " length: " + length);
+ mSocketOS.write(b, offset, length);
+ // There is no good way to confirm since the entire process is asynchronous anyway
+ if (VDBG) Log.d(TAG, "write out: " + mSocketOS + " length: " + length);
+ return length;
}
@Override
diff --git a/core/java/android/bluetooth/BluetoothUuid.java b/core/java/android/bluetooth/BluetoothUuid.java
index abdf949e..4b28516 100644
--- a/core/java/android/bluetooth/BluetoothUuid.java
+++ b/core/java/android/bluetooth/BluetoothUuid.java
@@ -73,6 +73,9 @@
public static final ParcelUuid MAS =
ParcelUuid.fromString("00001132-0000-1000-8000-00805F9B34FB");
+ public static final ParcelUuid BASE_UUID =
+ ParcelUuid.fromString("00000000-0000-1000-8000-00805F9B34FB");
+
public static final ParcelUuid[] RESERVED_UUIDS = {
AudioSink, AudioSource, AdvAudioDist, HSP, Handsfree, AvrcpController, AvrcpTarget,
@@ -211,4 +214,17 @@
long value = (uuid.getMostSignificantBits() & 0x0000FFFF00000000L) >>> 32;
return (int)value;
}
+
+ /**
+ * Check whether the given parcelUuid can be converted to 16 bit bluetooth uuid.
+ * @param parcelUuid
+ * @return true if the parcelUuid can be converted to 16 bit uuid, false otherwise.
+ */
+ public static boolean isShortUuid(ParcelUuid parcelUuid) {
+ UUID uuid = parcelUuid.getUuid();
+ if (uuid.getLeastSignificantBits() != BASE_UUID.getUuid().getLeastSignificantBits()) {
+ return false;
+ }
+ return ((uuid.getMostSignificantBits() & 0xFFFF0000FFFFFFFFL) == 0x1000L);
+ }
}
diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl
index df393db..784cdcc 100644
--- a/core/java/android/bluetooth/IBluetoothGatt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGatt.aidl
@@ -37,10 +37,15 @@
void unregisterClient(in int clientIf);
void clientConnect(in int clientIf, in String address, in boolean isDirect);
void clientDisconnect(in int clientIf, in String address);
- void clientListen(in int clientIf, in boolean start);
- void setAdvData(in int clientIf, in boolean setScanRsp, in boolean inclName,
- in boolean inclTxPower, in int minInterval, in int maxInterval,
- in int appearance, in byte[] manufacturerData);
+ void startAdvertising(in int appIf);
+ void stopAdvertising();
+ boolean setAdvServiceData(in byte[] serviceData);
+ byte[] getAdvServiceData();
+ boolean setAdvManufacturerCodeAndData(int manufactureCode, in byte[] manufacturerData);
+ byte[] getAdvManufacturerData();
+ List<ParcelUuid> getAdvServiceUuids();
+ void removeAdvManufacturerCodeAndData(int manufacturerCode);
+ boolean isAdvertising();
void refreshDevice(in int clientIf, in String address);
void discoverServices(in int clientIf, in String address);
void readCharacteristic(in int clientIf, in String address, in int srvcType,
@@ -75,7 +80,7 @@
void serverDisconnect(in int serverIf, in String address);
void beginServiceDeclaration(in int serverIf, in int srvcType,
in int srvcInstanceId, in int minHandles,
- in ParcelUuid srvcId);
+ in ParcelUuid srvcId, boolean advertisePreferred);
void addIncludedService(in int serverIf, in int srvcType,
in int srvcInstanceId, in ParcelUuid srvcId);
void addCharacteristic(in int serverIf, in ParcelUuid charId,
diff --git a/core/java/android/bluetooth/IBluetoothGattCallback.aidl b/core/java/android/bluetooth/IBluetoothGattCallback.aidl
index 60c297b..e3563fc 100644
--- a/core/java/android/bluetooth/IBluetoothGattCallback.aidl
+++ b/core/java/android/bluetooth/IBluetoothGattCallback.aidl
@@ -63,5 +63,4 @@
in int charInstId, in ParcelUuid charUuid,
in byte[] value);
void onReadRemoteRssi(in String address, in int rssi, in int status);
- void onListen(in int status);
}
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 093e0e9..a517bc5 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -115,6 +115,7 @@
* </p>
*
* @see #createVirtualDisplay
+ * @see #VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY
*/
public static final int VIRTUAL_DISPLAY_FLAG_PUBLIC = 1 << 0;
@@ -171,6 +172,22 @@
*/
public static final int VIRTUAL_DISPLAY_FLAG_SECURE = 1 << 2;
+ /**
+ * Virtual display flag: Only show this display's own content; do not mirror
+ * the content of another display.
+ *
+ * <p>
+ * This flag is used in conjunction with {@link #VIRTUAL_DISPLAY_FLAG_PUBLIC}.
+ * Ordinarily public virtual displays will automatically mirror the content of the
+ * default display if they have no windows of their own. When this flag is
+ * specified, the virtual display will only ever show its own content and
+ * will be blanked instead if it has no windows.
+ * </p>
+ *
+ * @see #createVirtualDisplay
+ */
+ public static final int VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY = 1 << 3;
+
/** @hide */
public DisplayManager(Context context) {
mContext = context;
@@ -429,8 +446,8 @@
* @param surface The surface to which the content of the virtual display should
* be rendered, must be non-null.
* @param flags A combination of virtual display flags:
- * {@link #VIRTUAL_DISPLAY_FLAG_PUBLIC}, {@link #VIRTUAL_DISPLAY_FLAG_PRESENTATION}
- * or {@link #VIRTUAL_DISPLAY_FLAG_SECURE}.
+ * {@link #VIRTUAL_DISPLAY_FLAG_PUBLIC}, {@link #VIRTUAL_DISPLAY_FLAG_PRESENTATION},
+ * {@link #VIRTUAL_DISPLAY_FLAG_SECURE}, or {@link #VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY}.
* @return The newly created virtual display, or null if the application could
* not create the virtual display.
*
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
new file mode 100644
index 0000000..8430973
--- /dev/null
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -0,0 +1,109 @@
+/*
+ * 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.hardware.display;
+
+import android.view.DisplayInfo;
+
+/**
+ * Display manager local system service interface.
+ *
+ * @hide Only for use within the system server.
+ */
+public abstract class DisplayManagerInternal {
+ /**
+ * Called by the power manager to blank all displays.
+ */
+ public abstract void blankAllDisplaysFromPowerManager();
+
+ /**
+ * Called by the power manager to unblank all displays.
+ */
+ public abstract void unblankAllDisplaysFromPowerManager();
+
+ /**
+ * Returns information about the specified logical display.
+ *
+ * @param displayId The logical display id.
+ * @return The logical display info, or null if the display does not exist. The
+ * returned object must be treated as immutable.
+ */
+ public abstract DisplayInfo getDisplayInfo(int displayId);
+
+ /**
+ * Registers a display transaction listener to provide the client a chance to
+ * update its surfaces within the same transaction as any display layout updates.
+ *
+ * @param listener The listener to register.
+ */
+ public abstract void registerDisplayTransactionListener(DisplayTransactionListener listener);
+
+ /**
+ * Unregisters a display transaction listener to provide the client a chance to
+ * update its surfaces within the same transaction as any display layout updates.
+ *
+ * @param listener The listener to unregister.
+ */
+ public abstract void unregisterDisplayTransactionListener(DisplayTransactionListener listener);
+
+ /**
+ * Overrides the display information of a particular logical display.
+ * This is used by the window manager to control the size and characteristics
+ * of the default display. It is expected to apply the requested change
+ * to the display information synchronously so that applications will immediately
+ * observe the new state.
+ *
+ * NOTE: This method must be the only entry point by which the window manager
+ * influences the logical configuration of displays.
+ *
+ * @param displayId The logical display id.
+ * @param info The new data to be stored.
+ */
+ public abstract void setDisplayInfoOverrideFromWindowManager(
+ int displayId, DisplayInfo info);
+
+ /**
+ * Called by the window manager to perform traversals while holding a
+ * surface flinger transaction.
+ */
+ public abstract void performTraversalInTransactionFromWindowManager();
+
+ /**
+ * Tells the display manager whether there is interesting unique content on the
+ * specified logical display. This is used to control automatic mirroring.
+ * <p>
+ * If the display has unique content, then the display manager arranges for it
+ * to be presented on a physical display if appropriate. Otherwise, the display manager
+ * may choose to make the physical display mirror some other logical display.
+ * </p>
+ *
+ * @param displayId The logical display id to update.
+ * @param hasContent True if the logical display has content.
+ * @param inTraversal True if called from WindowManagerService during a window traversal
+ * prior to call to performTraversalInTransactionFromWindowManager.
+ */
+ public abstract void setDisplayHasContent(int displayId, boolean hasContent,
+ boolean inTraversal);
+
+ /**
+ * Called within a Surface transaction whenever the size or orientation of a
+ * display may have changed. Provides an opportunity for the client to
+ * update the position of its surfaces as part of the same transaction.
+ */
+ public interface DisplayTransactionListener {
+ void onDisplayTransaction();
+ }
+}
diff --git a/services/java/com/android/server/display/DisplayViewport.java b/core/java/android/hardware/display/DisplayViewport.java
similarity index 96%
rename from services/java/com/android/server/display/DisplayViewport.java
rename to core/java/android/hardware/display/DisplayViewport.java
index 5080556..c2d498b 100644
--- a/services/java/com/android/server/display/DisplayViewport.java
+++ b/core/java/android/hardware/display/DisplayViewport.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.display;
+package android.hardware.display;
import android.graphics.Rect;
@@ -25,6 +25,8 @@
* This information is used by the input system to translate touch input from
* physical display coordinates into logical display coordinates.
* </p>
+ *
+ * @hide Only for use within the system server.
*/
public final class DisplayViewport {
// True if this viewport is valid.
diff --git a/core/java/android/hardware/input/InputManagerInternal.java b/core/java/android/hardware/input/InputManagerInternal.java
new file mode 100644
index 0000000..ecd32ea
--- /dev/null
+++ b/core/java/android/hardware/input/InputManagerInternal.java
@@ -0,0 +1,33 @@
+/*
+ * 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.hardware.input;
+
+import android.hardware.display.DisplayViewport;
+
+/**
+ * Input manager local system service interface.
+ *
+ * @hide Only for use within the system server.
+ */
+public abstract class InputManagerInternal {
+ /**
+ * Sets information about the displays as needed by the input system.
+ * The input system should copy this information if required.
+ */
+ public abstract void setDisplayViewports(DisplayViewport defaultViewport,
+ DisplayViewport externalTouchViewport);
+}
diff --git a/core/java/android/os/FactoryTest.java b/core/java/android/os/FactoryTest.java
index ec99697..7a252f9 100644
--- a/core/java/android/os/FactoryTest.java
+++ b/core/java/android/os/FactoryTest.java
@@ -25,6 +25,20 @@
* {@hide}
*/
public final class FactoryTest {
+ public static final int FACTORY_TEST_OFF = 0;
+ public static final int FACTORY_TEST_LOW_LEVEL = 1;
+ public static final int FACTORY_TEST_HIGH_LEVEL = 2;
+
+ /**
+ * Gets the current factory test mode.
+ *
+ * @return One of: {@link #FACTORY_TEST_OFF}, {@link #FACTORY_TEST_LOW_LEVEL},
+ * or {@link #FACTORY_TEST_HIGH_LEVEL}.
+ */
+ public static int getMode() {
+ return SystemProperties.getInt("ro.factorytest", FACTORY_TEST_OFF);
+ }
+
/**
* When true, long-press on power should immediately cause the device to
* shut down, without prompting the user.
diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java
new file mode 100644
index 0000000..cb3d528
--- /dev/null
+++ b/core/java/android/os/PowerManagerInternal.java
@@ -0,0 +1,60 @@
+/*
+ * 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.view.WindowManagerPolicy;
+
+/**
+ * Power manager local system service interface.
+ *
+ * @hide Only for use within the system server.
+ */
+public abstract class PowerManagerInternal {
+ /**
+ * Used by the window manager to override the screen brightness based on the
+ * current foreground activity.
+ *
+ * This method must only be called by the window manager.
+ *
+ * @param brightness The overridden brightness, or -1 to disable the override.
+ */
+ public abstract void setScreenBrightnessOverrideFromWindowManager(int brightness);
+
+ /**
+ * Used by the window manager to override the button brightness based on the
+ * current foreground activity.
+ *
+ * This method must only be called by the window manager.
+ *
+ * @param brightness The overridden brightness, or -1 to disable the override.
+ */
+ public abstract void setButtonBrightnessOverrideFromWindowManager(int brightness);
+
+ /**
+ * Used by the window manager to override the user activity timeout based on the
+ * current foreground activity. It can only be used to make the timeout shorter
+ * than usual, not longer.
+ *
+ * This method must only be called by the window manager.
+ *
+ * @param timeoutMillis The overridden timeout, or -1 to disable the override.
+ */
+ public abstract void setUserActivityTimeoutOverrideFromWindowManager(long timeoutMillis);
+
+ // TODO: Remove this and retrieve as a local service instead.
+ public abstract void setPolicy(WindowManagerPolicy policy);
+}
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index b22d5cf..a06a20b 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -79,9 +79,6 @@
private final String mName;
int mNativeObject; // package visibility only for Surface.java access
- private static final boolean HEADLESS = "1".equals(
- SystemProperties.get("ro.config.headless", "0"));
-
/* flags used in constructor (keep in sync with ISurfaceComposerClient.h) */
/**
@@ -232,8 +229,6 @@
new Throwable());
}
- checkHeadless();
-
mName = name;
mNativeObject = nativeCreate(session, name, w, h, format, flags);
if (mNativeObject == 0) {
@@ -619,10 +614,4 @@
}
nativeScreenshot(display, consumer, width, height, minLayer, maxLayer, allLayers);
}
-
- private static void checkHeadless() {
- if (HEADLESS) {
- throw new UnsupportedOperationException("Device is headless");
- }
- }
}
diff --git a/core/java/android/view/WindowManagerInternal.java b/core/java/android/view/WindowManagerInternal.java
new file mode 100644
index 0000000..a1bd4bd
--- /dev/null
+++ b/core/java/android/view/WindowManagerInternal.java
@@ -0,0 +1,33 @@
+/*
+ * 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.hardware.display.DisplayManagerInternal;
+
+/**
+ * Window manager local system service interface.
+ *
+ * @hide Only for use within the system server.
+ */
+public abstract class WindowManagerInternal {
+ /**
+ * Request that the window manager call
+ * {@link DisplayManagerInternal#performTraversalInTransactionFromWindowManager}
+ * within a surface transaction at a later time.
+ */
+ public abstract void requestTraversalFromDisplayManager();
+}
\ No newline at end of file
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index 00f4adb..879e58f 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -177,7 +177,8 @@
userId = UserHandle.myUserId();
}
IBinder iBinder = ServiceManager.getService(Context.ACCESSIBILITY_SERVICE);
- IAccessibilityManager service = IAccessibilityManager.Stub.asInterface(iBinder);
+ IAccessibilityManager service = iBinder == null
+ ? null : IAccessibilityManager.Stub.asInterface(iBinder);
sInstance = new AccessibilityManager(context, service, userId);
}
}
@@ -197,10 +198,14 @@
mHandler = new MyHandler(context.getMainLooper());
mService = service;
mUserId = userId;
-
+ if (mService == null) {
+ mIsEnabled = false;
+ }
try {
- final int stateFlags = mService.addClient(mClient, userId);
- setState(stateFlags);
+ if (mService != null) {
+ final int stateFlags = mService.addClient(mClient, userId);
+ setState(stateFlags);
+ }
} catch (RemoteException re) {
Log.e(LOG_TAG, "AccessibilityManagerService is dead", re);
}
@@ -322,14 +327,16 @@
public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList() {
List<AccessibilityServiceInfo> services = null;
try {
- services = mService.getInstalledAccessibilityServiceList(mUserId);
- if (DEBUG) {
- Log.i(LOG_TAG, "Installed AccessibilityServices " + services);
+ if (mService != null) {
+ services = mService.getInstalledAccessibilityServiceList(mUserId);
+ if (DEBUG) {
+ Log.i(LOG_TAG, "Installed AccessibilityServices " + services);
+ }
}
} catch (RemoteException re) {
Log.e(LOG_TAG, "Error while obtaining the installed AccessibilityServices. ", re);
}
- return Collections.unmodifiableList(services);
+ return services != null ? Collections.unmodifiableList(services) : Collections.EMPTY_LIST;
}
/**
@@ -349,14 +356,16 @@
int feedbackTypeFlags) {
List<AccessibilityServiceInfo> services = null;
try {
- services = mService.getEnabledAccessibilityServiceList(feedbackTypeFlags, mUserId);
- if (DEBUG) {
- Log.i(LOG_TAG, "Installed AccessibilityServices " + services);
+ if (mService != null) {
+ services = mService.getEnabledAccessibilityServiceList(feedbackTypeFlags, mUserId);
+ if (DEBUG) {
+ Log.i(LOG_TAG, "Installed AccessibilityServices " + services);
+ }
}
} catch (RemoteException re) {
Log.e(LOG_TAG, "Error while obtaining the installed AccessibilityServices. ", re);
}
- return Collections.unmodifiableList(services);
+ return services != null ? Collections.unmodifiableList(services) : Collections.EMPTY_LIST;
}
/**
@@ -466,6 +475,9 @@
*/
public int addAccessibilityInteractionConnection(IWindow windowToken,
IAccessibilityInteractionConnection connection) {
+ if (mService == null) {
+ return View.NO_ID;
+ }
try {
return mService.addAccessibilityInteractionConnection(windowToken, connection, mUserId);
} catch (RemoteException re) {
@@ -482,7 +494,9 @@
*/
public void removeAccessibilityInteractionConnection(IWindow windowToken) {
try {
- mService.removeAccessibilityInteractionConnection(windowToken);
+ if (mService != null) {
+ mService.removeAccessibilityInteractionConnection(windowToken);
+ }
} catch (RemoteException re) {
Log.e(LOG_TAG, "Error while removing an accessibility interaction connection. ", re);
}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 2e5fcec..8728610 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -26,6 +26,7 @@
import android.os.BatteryStats;
import android.os.FileUtils;
import android.os.Handler;
+import android.os.Looper;
import android.os.Message;
import android.os.Parcel;
import android.os.ParcelFormatException;
@@ -113,6 +114,10 @@
}
final class MyHandler extends Handler {
+ public MyHandler(Looper looper) {
+ super(looper, null, true);
+ }
+
@Override
public void handleMessage(Message msg) {
BatteryCallback cb = mCallback;
@@ -4487,9 +4492,9 @@
}
}
- public BatteryStatsImpl(String filename) {
+ public BatteryStatsImpl(String filename, Handler handler) {
mFile = new JournaledFile(new File(filename), new File(filename + ".tmp"));
- mHandler = new MyHandler();
+ mHandler = new MyHandler(handler.getLooper());
mStartCount++;
mScreenOnTimer = new StopwatchTimer(null, -1, null, mUnpluggables);
for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
diff --git a/core/java/com/android/internal/os/BinderInternal.java b/core/java/com/android/internal/os/BinderInternal.java
index f54a3e9..3b0f0f4 100644
--- a/core/java/com/android/internal/os/BinderInternal.java
+++ b/core/java/com/android/internal/os/BinderInternal.java
@@ -16,18 +16,11 @@
package com.android.internal.os;
-import android.os.Binder;
import android.os.IBinder;
import android.os.SystemClock;
import android.util.EventLog;
-import android.util.Log;
-import java.io.FileDescriptor;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.PrintWriter;
import java.lang.ref.WeakReference;
-import java.lang.reflect.Modifier;
/**
* Private and debugging Binder APIs.
diff --git a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
index 4654178..fe1cf72 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
@@ -164,8 +164,24 @@
}
actionView.setVisibility(item.isActionViewExpanded() ? View.GONE : View.VISIBLE);
+ final ActionMenuView menuParent = (ActionMenuView) parent;
+ final ViewGroup.LayoutParams lp = actionView.getLayoutParams();
+ if (!menuParent.checkLayoutParams(lp)) {
+ actionView.setLayoutParams(menuParent.generateLayoutParams(lp));
+ }
+ return actionView;
+ }
+
+ @Override
+ public void bindItemView(final MenuItemImpl item, MenuView.ItemView itemView) {
+ itemView.initialize(item, 0);
+
+ final ActionMenuView menuView = (ActionMenuView) mMenuView;
+ final ActionMenuItemView actionItemView = (ActionMenuItemView) itemView;
+ actionItemView.setItemInvoker(menuView);
+
if (item.hasSubMenu()) {
- actionView.setOnTouchListener(new ForwardingListener(actionView) {
+ actionItemView.setOnTouchListener(new ForwardingListener(actionItemView) {
@Override
public ListPopupWindow getPopup() {
return mActionButtonPopup != null ? mActionButtonPopup.getPopup() : null;
@@ -182,24 +198,8 @@
}
});
} else {
- actionView.setOnTouchListener(null);
+ actionItemView.setOnTouchListener(null);
}
-
- final ActionMenuView menuParent = (ActionMenuView) parent;
- final ViewGroup.LayoutParams lp = actionView.getLayoutParams();
- if (!menuParent.checkLayoutParams(lp)) {
- actionView.setLayoutParams(menuParent.generateLayoutParams(lp));
- }
- return actionView;
- }
-
- @Override
- public void bindItemView(MenuItemImpl item, MenuView.ItemView itemView) {
- itemView.initialize(item, 0);
-
- final ActionMenuView menuView = (ActionMenuView) mMenuView;
- ActionMenuItemView actionItemView = (ActionMenuItemView) itemView;
- actionItemView.setItemInvoker(menuView);
}
@Override
diff --git a/core/java/com/android/server/LocalServices.java b/core/java/com/android/server/LocalServices.java
new file mode 100644
index 0000000..25dcb30
--- /dev/null
+++ b/core/java/com/android/server/LocalServices.java
@@ -0,0 +1,60 @@
+/*
+ * 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.server;
+
+import android.util.ArrayMap;
+
+/**
+ * This class is used in a similar way as ServiceManager, except the services registered here
+ * are not Binder objects and are only available in the same process.
+ *
+ * Once all services are converted to the SystemService interface, this class can be absorbed
+ * into SystemServiceManager.
+ *
+ * {@hide}
+ */
+public final class LocalServices {
+ private LocalServices() {}
+
+ private static final ArrayMap<Class<?>, Object> sLocalServiceObjects =
+ new ArrayMap<Class<?>, Object>();
+
+ /**
+ * Returns a local service instance that implements the specified interface.
+ *
+ * @param type The type of service.
+ * @return The service object.
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> T getService(Class<T> type) {
+ synchronized (sLocalServiceObjects) {
+ return (T) sLocalServiceObjects.get(type);
+ }
+ }
+
+ /**
+ * Adds a service instance of the specified interface to the global registry of local services.
+ */
+ public static <T> void addService(Class<T> type, T service) {
+ synchronized (sLocalServiceObjects) {
+ if (sLocalServiceObjects.containsKey(type)) {
+ throw new IllegalStateException("Overriding service registration");
+ }
+ sLocalServiceObjects.put(type, service);
+ }
+ }
+}
diff --git a/core/java/com/android/server/SystemService.java b/core/java/com/android/server/SystemService.java
new file mode 100644
index 0000000..d69293a
--- /dev/null
+++ b/core/java/com/android/server/SystemService.java
@@ -0,0 +1,186 @@
+/*
+ * 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.server;
+
+import android.content.Context;
+import android.os.IBinder;
+import android.os.ServiceManager;
+
+/**
+ * The base class for services running in the system process. Override and implement
+ * the lifecycle event callback methods as needed.
+ *
+ * The lifecycle of a SystemService:
+ *
+ * {@link #onCreate(android.content.Context)} is called to initialize the
+ * service.
+ *
+ * {@link #onStart()} is called to get the service running. It is common
+ * for services to publish their Binder interface at this point. All required
+ * dependencies are also assumed to be ready to use.
+ *
+ * Then {@link #onBootPhase(int)} is called as many times as there are boot phases
+ * until {@link #PHASE_BOOT_COMPLETE} is sent, which is the last boot phase. Each phase
+ * is an opportunity to do special work, like acquiring optional service dependencies,
+ * waiting to see if SafeMode is enabled, or registering with a service that gets
+ * started after this one.
+ *
+ * NOTE: All lifecycle methods are called from the same thread that created the
+ * SystemService.
+ *
+ * {@hide}
+ */
+public abstract class SystemService {
+ /*
+ * Boot Phases
+ */
+ public static final int PHASE_WAIT_FOR_DEFAULT_DISPLAY = 100; // maybe should be a dependency?
+ public static final int PHASE_LOCK_SETTINGS_READY = 480;
+ public static final int PHASE_SYSTEM_SERVICES_READY = 500;
+ public static final int PHASE_THIRD_PARTY_APPS_CAN_START = 600;
+ public static final int PHASE_BOOT_COMPLETE = 1000;
+
+ private SystemServiceManager mManager;
+ private Context mContext;
+
+ final void init(Context context, SystemServiceManager manager) {
+ mContext = context;
+ mManager = manager;
+ onCreate(context);
+ }
+
+ public final boolean isSafeMode() {
+ return mManager.isSafeMode();
+ }
+
+ /**
+ * Services are not yet available. This is a good place to do setup work that does
+ * not require other services.
+ *
+ * @param context The system context.
+ */
+ public void onCreate(Context context) {}
+
+ /**
+ * Called when the dependencies listed in the @Service class-annotation are available
+ * and after the chosen start phase.
+ * When this method returns, the service should be published.
+ */
+ public abstract void onStart();
+
+ /**
+ * Called on each phase of the boot process. Phases before the service's start phase
+ * (as defined in the @Service annotation) are never received.
+ *
+ * @param phase The current boot phase.
+ */
+ public void onBootPhase(int phase) {}
+
+ /**
+ * Publish the service so it is accessible to other services and apps.
+ */
+ protected final void publishBinderService(String name, IBinder service) {
+ publishBinderService(name, service, false);
+ }
+
+ /**
+ * Publish the service so it is accessible to other services and apps.
+ */
+ protected final void publishBinderService(String name, IBinder service,
+ boolean allowIsolated) {
+ ServiceManager.addService(name, service, allowIsolated);
+ }
+
+ /**
+ * Get a binder service by its name.
+ */
+ protected final IBinder getBinderService(String name) {
+ return ServiceManager.getService(name);
+ }
+
+ /**
+ * Publish the service so it is only accessible to the system process.
+ */
+ protected final <T> void publishLocalService(Class<T> type, T service) {
+ LocalServices.addService(type, service);
+ }
+
+ /**
+ * Get a local service by interface.
+ */
+ protected final <T> T getLocalService(Class<T> type) {
+ return LocalServices.getService(type);
+ }
+
+ public final Context getContext() {
+ return mContext;
+ }
+
+// /**
+// * Called when a new user has been created. If your service deals with multiple users, this
+// * method should be overridden.
+// *
+// * @param userHandle The user that was created.
+// */
+// public void onUserCreated(int userHandle) {
+// }
+//
+// /**
+// * Called when an existing user has started a new session. If your service deals with multiple
+// * users, this method should be overridden.
+// *
+// * @param userHandle The user who started a new session.
+// */
+// public void onUserStarted(int userHandle) {
+// }
+//
+// /**
+// * Called when a background user session has entered the foreground. If your service deals with
+// * multiple users, this method should be overridden.
+// *
+// * @param userHandle The user who's session entered the foreground.
+// */
+// public void onUserForeground(int userHandle) {
+// }
+//
+// /**
+// * Called when a foreground user session has entered the background. If your service deals with
+// * multiple users, this method should be overridden;
+// *
+// * @param userHandle The user who's session entered the background.
+// */
+// public void onUserBackground(int userHandle) {
+// }
+//
+// /**
+// * Called when a user's active session has stopped. If your service deals with multiple users,
+// * this method should be overridden.
+// *
+// * @param userHandle The user who's session has stopped.
+// */
+// public void onUserStopped(int userHandle) {
+// }
+//
+// /**
+// * Called when a user has been removed from the system. If your service deals with multiple
+// * users, this method should be overridden.
+// *
+// * @param userHandle The user who has been removed.
+// */
+// public void onUserRemoved(int userHandle) {
+// }
+}
diff --git a/core/java/com/android/server/SystemServiceManager.java b/core/java/com/android/server/SystemServiceManager.java
new file mode 100644
index 0000000..06ad7f4
--- /dev/null
+++ b/core/java/com/android/server/SystemServiceManager.java
@@ -0,0 +1,177 @@
+/*
+ * 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.server;
+
+import android.content.Context;
+import android.util.Log;
+import android.util.Slog;
+
+import java.util.ArrayList;
+
+/**
+ * Manages creating, starting, and other lifecycle events of
+ * {@link com.android.server.SystemService}s.
+ *
+ * {@hide}
+ */
+public class SystemServiceManager {
+ private static final String TAG = "SystemServiceManager";
+
+ private final Context mContext;
+ private boolean mSafeMode;
+
+ // Services that should receive lifecycle events.
+ private final ArrayList<SystemService> mServices = new ArrayList<SystemService>();
+
+ private int mCurrentPhase = -1;
+
+ public SystemServiceManager(Context context) {
+ mContext = context;
+ }
+
+ /**
+ * Starts a service by name if the class exists, otherwise ignores it.
+ *
+ * @return The service instance, or null if not found.
+ */
+ @SuppressWarnings("unchecked")
+ public SystemService startServiceIfExists(String className) {
+ try {
+ return startService((Class<SystemService>)Class.forName(className));
+ } catch (ClassNotFoundException cnfe) {
+ Slog.i(TAG, className + " not available, ignoring.");
+ return null;
+ }
+ }
+
+ /**
+ * Creates and starts a system service. The class must be a subclass of
+ * {@link com.android.server.SystemService}.
+ *
+ * @param serviceClass A Java class that implements the SystemService interface.
+ * @return The service instance, never null.
+ * @throws RuntimeException if the service fails to start.
+ */
+ @SuppressWarnings("unchecked")
+ public <T extends SystemService> T startService(Class<T> serviceClass) {
+ final T serviceInstance = (T)createInstance(serviceClass);
+ try {
+ Slog.i(TAG, "Creating " + serviceClass.getSimpleName());
+ serviceInstance.init(mContext, this);
+ } catch (Throwable e) {
+ throw new RuntimeException("Failed to create service " + serviceClass.getName(), e);
+ }
+
+ mServices.add(serviceInstance);
+
+ try {
+ Slog.i(TAG, "Starting " + serviceClass.getSimpleName());
+ serviceInstance.onStart();
+ } catch (Throwable e) {
+ throw new RuntimeException("Failed to start service " + serviceClass.getName(), e);
+ }
+
+ return serviceInstance;
+ }
+
+ /**
+ * Starts the specified boot phase for all system services that have been started up to
+ * this point.
+ *
+ * @param phase The boot phase to start.
+ */
+ public void startBootPhase(final int phase) {
+ if (phase <= mCurrentPhase) {
+ throw new IllegalArgumentException("Next phase must be larger than previous");
+ }
+ mCurrentPhase = phase;
+
+ Slog.i(TAG, "Starting phase " + mCurrentPhase);
+
+ final int serviceLen = mServices.size();
+ for (int i = 0; i < serviceLen; i++) {
+ final SystemService service = mServices.get(i);
+ try {
+ service.onBootPhase(mCurrentPhase);
+ } catch (Throwable e) {
+ reportWtf("Service " + service.getClass().getName() +
+ " threw an Exception processing boot phase " + mCurrentPhase, e);
+ }
+ }
+ }
+
+ /** Sets the safe mode flag for services to query. */
+ public void setSafeMode(boolean safeMode) {
+ mSafeMode = safeMode;
+ }
+
+ /**
+ * Returns whether we are booting into safe mode.
+ * @return safe mode flag
+ */
+ public boolean isSafeMode() {
+ return mSafeMode;
+ }
+
+ /**
+ * Outputs the state of this manager to the System log.
+ */
+ public void dump() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("Current phase: ").append(mCurrentPhase).append("\n");
+ builder.append("Services:\n");
+ final int startedLen = mServices.size();
+ for (int i = 0; i < startedLen; i++) {
+ final SystemService service = mServices.get(i);
+ builder.append("\t")
+ .append(service.getClass().getSimpleName())
+ .append("\n");
+ }
+
+ Slog.e(TAG, builder.toString());
+ }
+
+ private SystemService createInstance(Class<?> clazz) {
+ // Make sure it's a type we expect
+ if (!SystemService.class.isAssignableFrom(clazz)) {
+ reportWtf("Class " + clazz.getName() + " does not extend " +
+ SystemService.class.getName());
+ }
+
+ try {
+ return (SystemService) clazz.newInstance();
+ } catch (InstantiationException e) {
+ reportWtf("Class " + clazz.getName() + " is abstract", e);
+ } catch (IllegalAccessException e) {
+ reportWtf("Class " + clazz.getName() +
+ " must have a public no-arg constructor", e);
+ }
+ return null;
+ }
+
+ private static void reportWtf(String message) {
+ reportWtf(message, null);
+ }
+
+ private static void reportWtf(String message, Throwable e) {
+ Slog.i(TAG, "******************************");
+ Log.wtf(TAG, message, e);
+
+ // Make sure we die
+ throw new RuntimeException(message, e);
+ }
+}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index b198937..e546117 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2522,7 +2522,7 @@
android:hasCode="false"
android:label="@string/android_system_label"
android:allowClearUserData="false"
- android:backupAgent="com.android.server.SystemBackupAgent"
+ android:backupAgent="com.android.server.backup.SystemBackupAgent"
android:killAfterRestore="false"
android:icon="@drawable/ic_launcher_android"
android:supportsRtl="true">
diff --git a/core/res/res/values/styles_micro.xml b/core/res/res/values/styles_micro.xml
new file mode 100644
index 0000000..2fd283e
--- /dev/null
+++ b/core/res/res/values/styles_micro.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+<resources>
+ <style name="Widget.Micro" parent="Widget.Holo" />
+
+ <style name="Widget.Micro.TextView">
+ <item name="android:fontFamily">sans-serif-condensed</item>
+ </style>
+</resources>
diff --git a/core/res/res/values/themes_micro.xml b/core/res/res/values/themes_micro.xml
new file mode 100644
index 0000000..be5fa99
--- /dev/null
+++ b/core/res/res/values/themes_micro.xml
@@ -0,0 +1,27 @@
+<?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.
+-->
+<resources>
+ <style name="Theme.Micro" parent="Theme.Holo" />
+
+ <style name="Theme.Micro.Light" parent="Theme.Holo.Light"/>
+ <style name="Theme.Micro.Light.NoActionBar" parent="Theme.Holo.Light.NoActionBar">
+ <item name="textViewStyle">@android:style/Widget.Micro.TextView</item>
+ </style>
+ <style name="Theme.Micro.Light.DarkActionBar" parent="Theme.Holo.Light.DarkActionBar">
+ <item name="textViewStyle">@android:style/Widget.Micro.TextView</item>
+ </style>
+
+</resources>
diff --git a/services/common_time/Android.mk b/libs/common_time/Android.mk
similarity index 100%
rename from services/common_time/Android.mk
rename to libs/common_time/Android.mk
diff --git a/services/common_time/clock_recovery.cpp b/libs/common_time/clock_recovery.cpp
similarity index 100%
rename from services/common_time/clock_recovery.cpp
rename to libs/common_time/clock_recovery.cpp
diff --git a/services/common_time/clock_recovery.h b/libs/common_time/clock_recovery.h
similarity index 100%
rename from services/common_time/clock_recovery.h
rename to libs/common_time/clock_recovery.h
diff --git a/services/common_time/common_clock.cpp b/libs/common_time/common_clock.cpp
similarity index 100%
rename from services/common_time/common_clock.cpp
rename to libs/common_time/common_clock.cpp
diff --git a/services/common_time/common_clock.h b/libs/common_time/common_clock.h
similarity index 100%
rename from services/common_time/common_clock.h
rename to libs/common_time/common_clock.h
diff --git a/services/common_time/common_clock_service.cpp b/libs/common_time/common_clock_service.cpp
similarity index 100%
rename from services/common_time/common_clock_service.cpp
rename to libs/common_time/common_clock_service.cpp
diff --git a/services/common_time/common_clock_service.h b/libs/common_time/common_clock_service.h
similarity index 100%
rename from services/common_time/common_clock_service.h
rename to libs/common_time/common_clock_service.h
diff --git a/services/common_time/common_time_config_service.cpp b/libs/common_time/common_time_config_service.cpp
similarity index 100%
rename from services/common_time/common_time_config_service.cpp
rename to libs/common_time/common_time_config_service.cpp
diff --git a/services/common_time/common_time_config_service.h b/libs/common_time/common_time_config_service.h
similarity index 100%
rename from services/common_time/common_time_config_service.h
rename to libs/common_time/common_time_config_service.h
diff --git a/services/common_time/common_time_server.cpp b/libs/common_time/common_time_server.cpp
similarity index 100%
rename from services/common_time/common_time_server.cpp
rename to libs/common_time/common_time_server.cpp
diff --git a/services/common_time/common_time_server.h b/libs/common_time/common_time_server.h
similarity index 100%
rename from services/common_time/common_time_server.h
rename to libs/common_time/common_time_server.h
diff --git a/services/common_time/common_time_server_api.cpp b/libs/common_time/common_time_server_api.cpp
similarity index 100%
rename from services/common_time/common_time_server_api.cpp
rename to libs/common_time/common_time_server_api.cpp
diff --git a/services/common_time/common_time_server_packets.cpp b/libs/common_time/common_time_server_packets.cpp
similarity index 100%
rename from services/common_time/common_time_server_packets.cpp
rename to libs/common_time/common_time_server_packets.cpp
diff --git a/services/common_time/common_time_server_packets.h b/libs/common_time/common_time_server_packets.h
similarity index 100%
rename from services/common_time/common_time_server_packets.h
rename to libs/common_time/common_time_server_packets.h
diff --git a/services/common_time/diag_thread.cpp b/libs/common_time/diag_thread.cpp
similarity index 100%
rename from services/common_time/diag_thread.cpp
rename to libs/common_time/diag_thread.cpp
diff --git a/services/common_time/diag_thread.h b/libs/common_time/diag_thread.h
similarity index 100%
rename from services/common_time/diag_thread.h
rename to libs/common_time/diag_thread.h
diff --git a/services/common_time/main.cpp b/libs/common_time/main.cpp
similarity index 100%
rename from services/common_time/main.cpp
rename to libs/common_time/main.cpp
diff --git a/services/common_time/utils.cpp b/libs/common_time/utils.cpp
similarity index 100%
rename from services/common_time/utils.cpp
rename to libs/common_time/utils.cpp
diff --git a/services/common_time/utils.h b/libs/common_time/utils.h
similarity index 100%
rename from services/common_time/utils.h
rename to libs/common_time/utils.h
diff --git a/services/input/Android.mk b/libs/input/Android.mk
similarity index 100%
rename from services/input/Android.mk
rename to libs/input/Android.mk
diff --git a/services/input/EventHub.cpp b/libs/input/EventHub.cpp
similarity index 100%
rename from services/input/EventHub.cpp
rename to libs/input/EventHub.cpp
diff --git a/services/input/EventHub.h b/libs/input/EventHub.h
similarity index 100%
rename from services/input/EventHub.h
rename to libs/input/EventHub.h
diff --git a/services/input/InputApplication.cpp b/libs/input/InputApplication.cpp
similarity index 100%
rename from services/input/InputApplication.cpp
rename to libs/input/InputApplication.cpp
diff --git a/services/input/InputApplication.h b/libs/input/InputApplication.h
similarity index 100%
rename from services/input/InputApplication.h
rename to libs/input/InputApplication.h
diff --git a/services/input/InputDispatcher.cpp b/libs/input/InputDispatcher.cpp
similarity index 100%
rename from services/input/InputDispatcher.cpp
rename to libs/input/InputDispatcher.cpp
diff --git a/services/input/InputDispatcher.h b/libs/input/InputDispatcher.h
similarity index 100%
rename from services/input/InputDispatcher.h
rename to libs/input/InputDispatcher.h
diff --git a/services/input/InputListener.cpp b/libs/input/InputListener.cpp
similarity index 100%
rename from services/input/InputListener.cpp
rename to libs/input/InputListener.cpp
diff --git a/services/input/InputListener.h b/libs/input/InputListener.h
similarity index 100%
rename from services/input/InputListener.h
rename to libs/input/InputListener.h
diff --git a/services/input/InputManager.cpp b/libs/input/InputManager.cpp
similarity index 100%
rename from services/input/InputManager.cpp
rename to libs/input/InputManager.cpp
diff --git a/services/input/InputManager.h b/libs/input/InputManager.h
similarity index 100%
rename from services/input/InputManager.h
rename to libs/input/InputManager.h
diff --git a/services/input/InputReader.cpp b/libs/input/InputReader.cpp
similarity index 100%
rename from services/input/InputReader.cpp
rename to libs/input/InputReader.cpp
diff --git a/services/input/InputReader.h b/libs/input/InputReader.h
similarity index 100%
rename from services/input/InputReader.h
rename to libs/input/InputReader.h
diff --git a/services/input/InputWindow.cpp b/libs/input/InputWindow.cpp
similarity index 100%
rename from services/input/InputWindow.cpp
rename to libs/input/InputWindow.cpp
diff --git a/services/input/InputWindow.h b/libs/input/InputWindow.h
similarity index 100%
rename from services/input/InputWindow.h
rename to libs/input/InputWindow.h
diff --git a/services/input/PointerController.cpp b/libs/input/PointerController.cpp
similarity index 100%
rename from services/input/PointerController.cpp
rename to libs/input/PointerController.cpp
diff --git a/services/input/PointerController.h b/libs/input/PointerController.h
similarity index 100%
rename from services/input/PointerController.h
rename to libs/input/PointerController.h
diff --git a/services/input/SpriteController.cpp b/libs/input/SpriteController.cpp
similarity index 100%
rename from services/input/SpriteController.cpp
rename to libs/input/SpriteController.cpp
diff --git a/services/input/SpriteController.h b/libs/input/SpriteController.h
similarity index 100%
rename from services/input/SpriteController.h
rename to libs/input/SpriteController.h
diff --git a/services/input/tests/Android.mk b/libs/input/tests/Android.mk
similarity index 100%
rename from services/input/tests/Android.mk
rename to libs/input/tests/Android.mk
diff --git a/services/input/tests/InputDispatcher_test.cpp b/libs/input/tests/InputDispatcher_test.cpp
similarity index 100%
rename from services/input/tests/InputDispatcher_test.cpp
rename to libs/input/tests/InputDispatcher_test.cpp
diff --git a/services/input/tests/InputReader_test.cpp b/libs/input/tests/InputReader_test.cpp
similarity index 100%
rename from services/input/tests/InputReader_test.cpp
rename to libs/input/tests/InputReader_test.cpp
diff --git a/policy/src/com/android/internal/policy/impl/PhoneLayoutInflater.java b/policy/src/com/android/internal/policy/impl/PhoneLayoutInflater.java
index 6bf4beb..968976b 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneLayoutInflater.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneLayoutInflater.java
@@ -26,7 +26,8 @@
public class PhoneLayoutInflater extends LayoutInflater {
private static final String[] sClassPrefixList = {
"android.widget.",
- "android.webkit."
+ "android.webkit.",
+ "android.app."
};
/**
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index c33bd35..f33ab40 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -231,7 +231,6 @@
/** If true, hitting shift & menu will broadcast Intent.ACTION_BUG_REPORT */
boolean mEnableShiftMenuBugReports = false;
- boolean mHeadless;
boolean mSafeMode;
WindowState mStatusBar = null;
int mStatusBarHeight;
@@ -855,7 +854,6 @@
mContext = context;
mWindowManager = windowManager;
mWindowManagerFuncs = windowManagerFuncs;
- mHeadless = "1".equals(SystemProperties.get("ro.config.headless", "0"));
mHandler = new PolicyHandler();
mOrientationListener = new MyOrientationListener(mContext, mHandler);
try {
@@ -3602,9 +3600,6 @@
/** {@inheritDoc} */
public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
- // do nothing if headless
- if (mHeadless) return;
-
// lid changed state
final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED;
if (newLidState == mLidState) {
@@ -3837,7 +3832,7 @@
// the device some other way (which is why we have an exemption here for injected
// events).
int result;
- if ((isScreenOn && !mHeadless) || (isInjected && !isWakeKey)) {
+ if (isScreenOn || (isInjected && !isWakeKey)) {
// When the screen is on or if the key is injected pass the key to the application.
result = ACTION_PASS_TO_USER;
} else {
@@ -4663,10 +4658,9 @@
/** {@inheritDoc} */
@Override
public void systemReady() {
- if (!mHeadless) {
- mKeyguardDelegate = new KeyguardServiceDelegate(mContext, null);
- mKeyguardDelegate.onSystemReady();
- }
+ mKeyguardDelegate = new KeyguardServiceDelegate(mContext, null);
+ mKeyguardDelegate.onSystemReady();
+
synchronized (mLock) {
updateOrientationListenerLp();
mSystemReady = true;
@@ -4693,7 +4687,6 @@
/** {@inheritDoc} */
public void showBootMessage(final CharSequence msg, final boolean always) {
- if (mHeadless) return;
mHandler.post(new Runnable() {
@Override public void run() {
if (mBootMsgDialog == null) {
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java
index 1357462..e5af716 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java
@@ -109,6 +109,9 @@
if (!context.bindServiceAsUser(intent, mKeyguardConnection,
Context.BIND_AUTO_CREATE, UserHandle.OWNER)) {
if (DEBUG) Log.v(TAG, "*** Keyguard: can't bind to " + KEYGUARD_CLASS);
+ mKeyguardState.showing = false;
+ mKeyguardState.showingAndNotHidden = false;
+ mKeyguardState.secure = false;
} else {
if (DEBUG) Log.v(TAG, "*** Keyguard started");
}
diff --git a/services/Android.mk b/services/Android.mk
new file mode 100644
index 0000000..80fd35a
--- /dev/null
+++ b/services/Android.mk
@@ -0,0 +1,49 @@
+LOCAL_PATH:= $(call my-dir)
+
+# the java library
+# ============================================================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES :=
+
+# TODO: Move this to the product makefiles
+REQUIRED_SERVICES := core accessibility appwidget backup devicepolicy print
+
+include $(patsubst %,$(LOCAL_PATH)/%/java/service.mk,$(REQUIRED_SERVICES))
+
+LOCAL_MODULE:= services
+
+LOCAL_JAVA_LIBRARIES := android.policy conscrypt telephony-common
+
+#LOCAL_PROGUARD_ENABLED := full
+#LOCAL_PROGUARD_FLAG_FILES := proguard.flags
+
+include $(BUILD_JAVA_LIBRARY)
+
+include $(BUILD_DROIDDOC)
+
+# native library
+# =============================================================
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES :=
+LOCAL_SHARED_LIBRARIES :=
+
+# include all the jni subdirs to collect their sources
+include $(wildcard $(LOCAL_PATH)/*/jni/Android.mk)
+
+LOCAL_CFLAGS += -DEGL_EGLEXT_PROTOTYPES -DGL_GLEXT_PROTOTYPES
+
+ifeq ($(WITH_MALLOC_LEAK_CHECK),true)
+ LOCAL_CFLAGS += -DMALLOC_LEAK_CHECK
+endif
+
+LOCAL_MODULE:= libandroid_servers
+
+include $(BUILD_SHARED_LIBRARY)
+
+ifeq (,$(ONE_SHOT_MAKEFILE))
+include $(call all-makefiles-under, $(LOCAL_PATH))
+endif
+
diff --git a/services/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
similarity index 100%
rename from services/java/com/android/server/accessibility/AccessibilityInputFilter.java
rename to services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
similarity index 100%
rename from services/java/com/android/server/accessibility/AccessibilityManagerService.java
rename to services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
diff --git a/services/java/com/android/server/accessibility/EventStreamTransformation.java b/services/accessibility/java/com/android/server/accessibility/EventStreamTransformation.java
similarity index 100%
rename from services/java/com/android/server/accessibility/EventStreamTransformation.java
rename to services/accessibility/java/com/android/server/accessibility/EventStreamTransformation.java
diff --git a/services/java/com/android/server/accessibility/GestureUtils.java b/services/accessibility/java/com/android/server/accessibility/GestureUtils.java
similarity index 100%
rename from services/java/com/android/server/accessibility/GestureUtils.java
rename to services/accessibility/java/com/android/server/accessibility/GestureUtils.java
diff --git a/services/java/com/android/server/accessibility/ScreenMagnifier.java b/services/accessibility/java/com/android/server/accessibility/ScreenMagnifier.java
similarity index 100%
rename from services/java/com/android/server/accessibility/ScreenMagnifier.java
rename to services/accessibility/java/com/android/server/accessibility/ScreenMagnifier.java
diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
similarity index 100%
rename from services/java/com/android/server/accessibility/TouchExplorer.java
rename to services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
diff --git a/services/accessibility/java/service.mk b/services/accessibility/java/service.mk
new file mode 100644
index 0000000..5e8f375
--- /dev/null
+++ b/services/accessibility/java/service.mk
@@ -0,0 +1,11 @@
+# Include only if the service is required
+ifneq ($(findstring accessibility,$(REQUIRED_SERVICES)),)
+
+SUB_DIR := accessibility/java
+
+LOCAL_SRC_FILES += \
+ $(call all-java-files-under,$(SUB_DIR))
+
+#DEFINED_SERVICES += com.android.server.accessibility.AccessibilityManagerService
+
+endif
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java
new file mode 100644
index 0000000..3378e3d
--- /dev/null
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java
@@ -0,0 +1,384 @@
+/*
+ * Copyright (C) 2007 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.appwidget;
+
+import android.app.ActivityManager;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.widget.RemoteViews;
+
+import com.android.internal.appwidget.IAppWidgetHost;
+import com.android.internal.appwidget.IAppWidgetService;
+import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.SystemService;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.List;
+import java.util.Locale;
+
+
+/**
+ * SystemService that publishes an IAppWidgetService.
+ */
+public class AppWidgetService extends SystemService {
+
+ static final String TAG = "AppWidgetService";
+
+ Context mContext;
+ Handler mSaveStateHandler;
+
+ SparseArray<AppWidgetServiceImpl> mAppWidgetServices;
+
+ @Override
+ public void onCreate(Context context) {
+ mContext = context;
+
+ mSaveStateHandler = BackgroundThread.getHandler();
+
+ mAppWidgetServices = new SparseArray<AppWidgetServiceImpl>(5);
+ AppWidgetServiceImpl primary = new AppWidgetServiceImpl(context, 0, mSaveStateHandler);
+ mAppWidgetServices.append(0, primary);
+ }
+
+ @Override
+ public void onStart() {
+ publishBinderService(Context.APPWIDGET_SERVICE, mServiceImpl);
+ }
+
+ @Override
+ public void onBootPhase(int phase) {
+ if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
+ mServiceImpl.systemRunning(isSafeMode());
+ }
+ }
+
+ private final AppWidgetServiceStub mServiceImpl = new AppWidgetServiceStub();
+
+ private class AppWidgetServiceStub extends IAppWidgetService.Stub {
+
+ private boolean mSafeMode;
+ private Locale mLocale;
+ private PackageManager mPackageManager;
+
+ public void systemRunning(boolean safeMode) {
+ mSafeMode = safeMode;
+
+ mAppWidgetServices.get(0).systemReady(safeMode);
+
+ // Register for the boot completed broadcast, so we can send the
+ // ENABLE broacasts. If we try to send them now, they time out,
+ // because the system isn't ready to handle them yet.
+ mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
+ new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null);
+
+ // Register for configuration changes so we can update the names
+ // of the widgets when the locale changes.
+ mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
+ new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED), null, null);
+
+ // Register for broadcasts about package install, etc., so we can
+ // update the provider list.
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_PACKAGE_ADDED);
+ filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+ filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ filter.addDataScheme("package");
+ mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
+ filter, null, null);
+ // Register for events related to sdcard installation.
+ IntentFilter sdFilter = new IntentFilter();
+ sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
+ sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
+ mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
+ sdFilter, null, null);
+
+ IntentFilter userFilter = new IntentFilter();
+ userFilter.addAction(Intent.ACTION_USER_REMOVED);
+ userFilter.addAction(Intent.ACTION_USER_STOPPING);
+ mContext.registerReceiver(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
+ onUserRemoved(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
+ UserHandle.USER_NULL));
+ } else if (Intent.ACTION_USER_STOPPING.equals(intent.getAction())) {
+ onUserStopping(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
+ UserHandle.USER_NULL));
+ }
+ }
+ }, userFilter);
+ }
+
+ @Override
+ public int allocateAppWidgetId(String packageName, int hostId, int userId)
+ throws RemoteException {
+ return getImplForUser(userId).allocateAppWidgetId(packageName, hostId);
+ }
+
+ @Override
+ public int[] getAppWidgetIdsForHost(int hostId, int userId) throws RemoteException {
+ return getImplForUser(userId).getAppWidgetIdsForHost(hostId);
+ }
+
+ @Override
+ public void deleteAppWidgetId(int appWidgetId, int userId) throws RemoteException {
+ getImplForUser(userId).deleteAppWidgetId(appWidgetId);
+ }
+
+ @Override
+ public void deleteHost(int hostId, int userId) throws RemoteException {
+ getImplForUser(userId).deleteHost(hostId);
+ }
+
+ @Override
+ public void deleteAllHosts(int userId) throws RemoteException {
+ getImplForUser(userId).deleteAllHosts();
+ }
+
+ @Override
+ public void bindAppWidgetId(int appWidgetId, ComponentName provider, Bundle options,
+ int userId) throws RemoteException {
+ getImplForUser(userId).bindAppWidgetId(appWidgetId, provider, options);
+ }
+
+ @Override
+ public boolean bindAppWidgetIdIfAllowed(
+ String packageName, int appWidgetId, ComponentName provider, Bundle options,
+ int userId) throws RemoteException {
+ return getImplForUser(userId).bindAppWidgetIdIfAllowed(
+ packageName, appWidgetId, provider, options);
+ }
+
+ @Override
+ public boolean hasBindAppWidgetPermission(String packageName, int userId)
+ throws RemoteException {
+ return getImplForUser(userId).hasBindAppWidgetPermission(packageName);
+ }
+
+ @Override
+ public void setBindAppWidgetPermission(String packageName, boolean permission, int userId)
+ throws RemoteException {
+ getImplForUser(userId).setBindAppWidgetPermission(packageName, permission);
+ }
+
+ @Override
+ public void bindRemoteViewsService(int appWidgetId, Intent intent, IBinder connection,
+ int userId) throws RemoteException {
+ getImplForUser(userId).bindRemoteViewsService(appWidgetId, intent, connection);
+ }
+
+ @Override
+ public int[] startListening(IAppWidgetHost host, String packageName, int hostId,
+ List<RemoteViews> updatedViews, int userId) throws RemoteException {
+ return getImplForUser(userId).startListening(host, packageName, hostId, updatedViews);
+ }
+
+ public void onUserRemoved(int userId) {
+ if (userId < 1) return;
+ synchronized (mAppWidgetServices) {
+ AppWidgetServiceImpl impl = mAppWidgetServices.get(userId);
+ mAppWidgetServices.remove(userId);
+
+ if (impl == null) {
+ AppWidgetServiceImpl.getSettingsFile(userId).delete();
+ } else {
+ impl.onUserRemoved();
+ }
+ }
+ }
+
+ public void onUserStopping(int userId) {
+ if (userId < 1) return;
+ synchronized (mAppWidgetServices) {
+ AppWidgetServiceImpl impl = mAppWidgetServices.get(userId);
+ if (impl != null) {
+ mAppWidgetServices.remove(userId);
+ impl.onUserStopping();
+ }
+ }
+ }
+
+ private void checkPermission(int userId) {
+ int realUserId = ActivityManager.handleIncomingUser(
+ Binder.getCallingPid(),
+ Binder.getCallingUid(),
+ userId,
+ false, /* allowAll */
+ true, /* requireFull */
+ this.getClass().getSimpleName(),
+ this.getClass().getPackage().getName());
+ }
+
+ private AppWidgetServiceImpl getImplForUser(int userId) {
+ checkPermission(userId);
+ boolean sendInitial = false;
+ AppWidgetServiceImpl service;
+ synchronized (mAppWidgetServices) {
+ service = mAppWidgetServices.get(userId);
+ if (service == null) {
+ Slog.i(TAG, "Unable to find AppWidgetServiceImpl for user " + userId
+ + ", adding");
+ // TODO: Verify that it's a valid user
+ service = new AppWidgetServiceImpl(mContext, userId, mSaveStateHandler);
+ service.systemReady(mSafeMode);
+ // Assume that BOOT_COMPLETED was received, as this is a non-primary user.
+ mAppWidgetServices.append(userId, service);
+ sendInitial = true;
+ }
+ }
+ if (sendInitial) {
+ service.sendInitialBroadcasts();
+ }
+ return service;
+ }
+
+ @Override
+ public int[] getAppWidgetIds(ComponentName provider, int userId) throws RemoteException {
+ return getImplForUser(userId).getAppWidgetIds(provider);
+ }
+
+ @Override
+ public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId, int userId)
+ throws RemoteException {
+ return getImplForUser(userId).getAppWidgetInfo(appWidgetId);
+ }
+
+ @Override
+ public RemoteViews getAppWidgetViews(int appWidgetId, int userId) throws RemoteException {
+ return getImplForUser(userId).getAppWidgetViews(appWidgetId);
+ }
+
+ @Override
+ public void updateAppWidgetOptions(int appWidgetId, Bundle options, int userId) {
+ getImplForUser(userId).updateAppWidgetOptions(appWidgetId, options);
+ }
+
+ @Override
+ public Bundle getAppWidgetOptions(int appWidgetId, int userId) {
+ return getImplForUser(userId).getAppWidgetOptions(appWidgetId);
+ }
+
+ @Override
+ public List<AppWidgetProviderInfo> getInstalledProviders(int categoryFilter, int userId)
+ throws RemoteException {
+ return getImplForUser(userId).getInstalledProviders(categoryFilter);
+ }
+
+ @Override
+ public void notifyAppWidgetViewDataChanged(int[] appWidgetIds, int viewId, int userId)
+ throws RemoteException {
+ getImplForUser(userId).notifyAppWidgetViewDataChanged(
+ appWidgetIds, viewId);
+ }
+
+ @Override
+ public void partiallyUpdateAppWidgetIds(int[] appWidgetIds, RemoteViews views, int userId)
+ throws RemoteException {
+ getImplForUser(userId).partiallyUpdateAppWidgetIds(
+ appWidgetIds, views);
+ }
+
+ @Override
+ public void stopListening(int hostId, int userId) throws RemoteException {
+ getImplForUser(userId).stopListening(hostId);
+ }
+
+ @Override
+ public void unbindRemoteViewsService(int appWidgetId, Intent intent, int userId)
+ throws RemoteException {
+ getImplForUser(userId).unbindRemoteViewsService(
+ appWidgetId, intent);
+ }
+
+ @Override
+ public void updateAppWidgetIds(int[] appWidgetIds, RemoteViews views, int userId)
+ throws RemoteException {
+ getImplForUser(userId).updateAppWidgetIds(appWidgetIds, views);
+ }
+
+ @Override
+ public void updateAppWidgetProvider(ComponentName provider, RemoteViews views, int userId)
+ throws RemoteException {
+ getImplForUser(userId).updateAppWidgetProvider(provider, views);
+ }
+
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+
+ // Dump the state of all the app widget providers
+ synchronized (mAppWidgetServices) {
+ IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
+ for (int i = 0; i < mAppWidgetServices.size(); i++) {
+ pw.println("User: " + mAppWidgetServices.keyAt(i));
+ ipw.increaseIndent();
+ AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i);
+ service.dump(fd, ipw, args);
+ ipw.decreaseIndent();
+ }
+ }
+ }
+
+ BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ // Slog.d(TAG, "received " + action);
+ if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
+ int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
+ if (userId >= 0) {
+ getImplForUser(userId).sendInitialBroadcasts();
+ } else {
+ Slog.w(TAG, "Incorrect user handle supplied in " + intent);
+ }
+ } else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
+ for (int i = 0; i < mAppWidgetServices.size(); i++) {
+ AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i);
+ service.onConfigurationChanged();
+ }
+ } else {
+ int sendingUser = getSendingUserId();
+ if (sendingUser == UserHandle.USER_ALL) {
+ for (int i = 0; i < mAppWidgetServices.size(); i++) {
+ AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i);
+ service.onBroadcastReceived(intent);
+ }
+ } else {
+ AppWidgetServiceImpl service = mAppWidgetServices.get(sendingUser);
+ if (service != null) {
+ service.onBroadcastReceived(intent);
+ }
+ }
+ }
+ }
+ };
+ }
+}
diff --git a/services/java/com/android/server/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
similarity index 99%
rename from services/java/com/android/server/AppWidgetServiceImpl.java
rename to services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 69ae846..98dead3 100644
--- a/services/java/com/android/server/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server;
+package com.android.server.appwidget;
import android.app.AlarmManager;
import android.app.AppGlobals;
diff --git a/services/appwidget/java/service.mk b/services/appwidget/java/service.mk
new file mode 100644
index 0000000..0e33446
--- /dev/null
+++ b/services/appwidget/java/service.mk
@@ -0,0 +1,11 @@
+# Include only if the service is required
+ifneq ($(findstring appwidget,$(REQUIRED_SERVICES)),)
+
+SUB_DIR := appwidget/java
+
+LOCAL_SRC_FILES += \
+ $(call all-java-files-under,$(SUB_DIR))
+
+#DEFINED_SERVICES += com.android.server.appwidget.AppWidgetService
+
+endif
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
similarity index 99%
rename from services/java/com/android/server/BackupManagerService.java
rename to services/backup/java/com/android/server/backup/BackupManagerService.java
index 00bfee7..c6dc5e6 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server;
+package com.android.server.backup;
import android.app.ActivityManagerNative;
import android.app.AlarmManager;
@@ -83,7 +83,9 @@
import com.android.internal.backup.IBackupTransport;
import com.android.internal.backup.IObbBackupService;
import com.android.internal.backup.LocalTransport;
-import com.android.server.PackageManagerBackupAgent.Metadata;
+import com.android.server.EventLogTags;
+import com.android.server.SystemService;
+import com.android.server.backup.PackageManagerBackupAgent.Metadata;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
@@ -135,7 +137,8 @@
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
-class BackupManagerService extends IBackupManager.Stub {
+public class BackupManagerService extends IBackupManager.Stub {
+
private static final String TAG = "BackupManagerService";
private static final boolean DEBUG = true;
private static final boolean MORE_DEBUG = false;
@@ -1178,7 +1181,8 @@
// First, on an encrypted device we require matching the device pw
final boolean isEncrypted;
try {
- isEncrypted = (mMountService.getEncryptionState() != MountService.ENCRYPTION_STATE_NONE);
+ isEncrypted = (mMountService.getEncryptionState() !=
+ IMountService.ENCRYPTION_STATE_NONE);
if (isEncrypted) {
if (DEBUG) {
Slog.i(TAG, "Device encrypted; verifying against device data pw");
@@ -5437,7 +5441,8 @@
boolean isEncrypted;
try {
- isEncrypted = (mMountService.getEncryptionState() != MountService.ENCRYPTION_STATE_NONE);
+ isEncrypted = (mMountService.getEncryptionState() !=
+ IMountService.ENCRYPTION_STATE_NONE);
if (isEncrypted) Slog.w(TAG, "Device is encrypted; forcing enc password");
} catch (RemoteException e) {
// couldn't contact the mount service; fail "safe" and assume encryption
@@ -6086,7 +6091,7 @@
}
}
- // clean up the BackupManagerService side of the bookkeeping
+ // clean up the BackupManagerImpl side of the bookkeeping
// and cancel any pending timeout message
mBackupManager.clearRestoreSession(mSession);
}
diff --git a/services/backup/java/com/android/server/backup/BackupManagerSystemService.java b/services/backup/java/com/android/server/backup/BackupManagerSystemService.java
new file mode 100644
index 0000000..db2c94a
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/BackupManagerSystemService.java
@@ -0,0 +1,36 @@
+/*
+ * 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.server.backup;
+
+import android.content.Context;
+
+import com.android.server.SystemService;
+
+public class BackupManagerSystemService extends SystemService {
+ private BackupManagerService mBackupManagerImpl;
+
+ @Override
+ public void onCreate(Context context) {
+ mBackupManagerImpl = new BackupManagerService(context);
+ }
+
+ @Override
+ public void onStart() {
+ publishBinderService(Context.BACKUP_SERVICE, mBackupManagerImpl);
+ }
+}
+
diff --git a/services/java/com/android/server/PackageManagerBackupAgent.java b/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java
similarity index 99%
rename from services/java/com/android/server/PackageManagerBackupAgent.java
rename to services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java
index 77bddb0..495da88 100644
--- a/services/java/com/android/server/PackageManagerBackupAgent.java
+++ b/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server;
+package com.android.server.backup;
import android.app.backup.BackupAgent;
import android.app.backup.BackupDataInput;
diff --git a/services/java/com/android/server/SystemBackupAgent.java b/services/backup/java/com/android/server/backup/SystemBackupAgent.java
similarity index 79%
rename from services/java/com/android/server/SystemBackupAgent.java
rename to services/backup/java/com/android/server/backup/SystemBackupAgent.java
index 8cf273d..26e2e2a 100644
--- a/services/java/com/android/server/SystemBackupAgent.java
+++ b/services/backup/java/com/android/server/backup/SystemBackupAgent.java
@@ -14,9 +14,10 @@
* limitations under the License.
*/
-package com.android.server;
+package com.android.server.backup;
+import android.app.IWallpaperManager;
import android.app.backup.BackupDataInput;
import android.app.backup.BackupDataOutput;
import android.app.backup.BackupAgentHelper;
@@ -26,11 +27,11 @@
import android.content.Context;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.util.Slog;
-
import java.io.File;
import java.io.IOException;
@@ -63,16 +64,23 @@
public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
ParcelFileDescriptor newState) throws IOException {
// We only back up the data under the current "wallpaper" schema with metadata
- WallpaperManagerService wallpaper = (WallpaperManagerService)ServiceManager.getService(
+ IWallpaperManager wallpaper = (IWallpaperManager)ServiceManager.getService(
Context.WALLPAPER_SERVICE);
String[] files = new String[] { WALLPAPER_IMAGE, WALLPAPER_INFO };
String[] keys = new String[] { WALLPAPER_IMAGE_KEY, WALLPAPER_INFO_KEY };
- if (wallpaper != null && wallpaper.getName() != null && wallpaper.getName().length() > 0) {
- // When the wallpaper has a name, back up the info by itself.
- // TODO: Don't rely on the innards of the service object like this!
- // TODO: Send a delete for any stored wallpaper image in this case?
- files = new String[] { WALLPAPER_INFO };
- keys = new String[] { WALLPAPER_INFO_KEY };
+ if (wallpaper != null) {
+ try {
+ final String wallpaperName = wallpaper.getName();
+ if (wallpaperName != null && wallpaperName.length() > 0) {
+ // When the wallpaper has a name, back up the info by itself.
+ // TODO: Don't rely on the innards of the service object like this!
+ // TODO: Send a delete for any stored wallpaper image in this case?
+ files = new String[] { WALLPAPER_INFO };
+ keys = new String[] { WALLPAPER_INFO_KEY };
+ }
+ } catch (RemoteException re) {
+ Slog.e(TAG, "Couldn't get wallpaper name\n" + re);
+ }
}
addHelper("wallpaper", new WallpaperBackupHelper(SystemBackupAgent.this, files, keys));
super.onBackup(oldState, data, newState);
@@ -109,9 +117,15 @@
try {
super.onRestore(data, appVersionCode, newState);
- WallpaperManagerService wallpaper = (WallpaperManagerService)ServiceManager.getService(
+ IWallpaperManager wallpaper = (IWallpaperManager) ServiceManager.getService(
Context.WALLPAPER_SERVICE);
- wallpaper.settingsRestored();
+ if (wallpaper != null) {
+ try {
+ wallpaper.settingsRestored();
+ } catch (RemoteException re) {
+ Slog.e(TAG, "Couldn't restore settings\n" + re);
+ }
+ }
} catch (IOException ex) {
// If there was a failure, delete everything for the wallpaper, this is too aggressive,
// but this is hopefully a rare failure.
@@ -149,10 +163,16 @@
FullBackup.restoreFile(data, size, type, mode, mtime, outFile);
if (restoredWallpaper) {
- WallpaperManagerService wallpaper =
- (WallpaperManagerService)ServiceManager.getService(
+ IWallpaperManager wallpaper =
+ (IWallpaperManager)ServiceManager.getService(
Context.WALLPAPER_SERVICE);
- wallpaper.settingsRestored();
+ if (wallpaper != null) {
+ try {
+ wallpaper.settingsRestored();
+ } catch (RemoteException re) {
+ Slog.e(TAG, "Couldn't restore settings\n" + re);
+ }
+ }
}
} catch (IOException e) {
if (restoredWallpaper) {
diff --git a/services/backup/java/service.mk b/services/backup/java/service.mk
new file mode 100644
index 0000000..bd22b95
--- /dev/null
+++ b/services/backup/java/service.mk
@@ -0,0 +1,11 @@
+# Include only if the service is required
+ifneq ($(findstring backup,$(REQUIRED_SERVICES)),)
+
+SUB_DIR := backup/java
+
+LOCAL_SRC_FILES += \
+ $(call all-java-files-under,$(SUB_DIR))
+
+#DEFINED_SERVICES += com.android.server.backup.BackupManagerService
+
+endif
diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
similarity index 88%
rename from services/java/com/android/server/AlarmManagerService.java
rename to services/core/java/com/android/server/AlarmManagerService.java
index 2e1b0af..3cdf170 100644
--- a/services/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -31,6 +31,7 @@
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
+import android.os.IBinder;
import android.os.Message;
import android.os.PowerManager;
import android.os.SystemClock;
@@ -64,54 +65,51 @@
import com.android.internal.util.LocalLog;
-class AlarmManagerService extends IAlarmManager.Stub {
+class AlarmManagerService extends SystemService {
// The threshold for how long an alarm can be late before we print a
// warning message. The time duration is in milliseconds.
private static final long LATE_ALARM_THRESHOLD = 10 * 1000;
private static final int RTC_WAKEUP_MASK = 1 << RTC_WAKEUP;
private static final int RTC_MASK = 1 << RTC;
- private static final int ELAPSED_REALTIME_WAKEUP_MASK = 1 << ELAPSED_REALTIME_WAKEUP;
+ private static final int ELAPSED_REALTIME_WAKEUP_MASK = 1 << ELAPSED_REALTIME_WAKEUP;
private static final int ELAPSED_REALTIME_MASK = 1 << ELAPSED_REALTIME;
- private static final int TIME_CHANGED_MASK = 1 << 16;
- private static final int IS_WAKEUP_MASK = RTC_WAKEUP_MASK|ELAPSED_REALTIME_WAKEUP_MASK;
+ static final int TIME_CHANGED_MASK = 1 << 16;
+ static final int IS_WAKEUP_MASK = RTC_WAKEUP_MASK|ELAPSED_REALTIME_WAKEUP_MASK;
// Mask for testing whether a given alarm type is wakeup vs non-wakeup
- private static final int TYPE_NONWAKEUP_MASK = 0x1; // low bit => non-wakeup
+ static final int TYPE_NONWAKEUP_MASK = 0x1; // low bit => non-wakeup
- private static final String TAG = "AlarmManager";
- private static final String ClockReceiver_TAG = "ClockReceiver";
- private static final boolean localLOGV = false;
- private static final boolean DEBUG_BATCH = localLOGV || false;
- private static final boolean DEBUG_VALIDATE = localLOGV || false;
- private static final int ALARM_EVENT = 1;
- private static final String TIMEZONE_PROPERTY = "persist.sys.timezone";
+ static final String TAG = "AlarmManager";
+ static final String ClockReceiver_TAG = "ClockReceiver";
+ static final boolean localLOGV = false;
+ static final boolean DEBUG_BATCH = localLOGV || false;
+ static final boolean DEBUG_VALIDATE = localLOGV || false;
+ static final int ALARM_EVENT = 1;
+ static final String TIMEZONE_PROPERTY = "persist.sys.timezone";
- private static final Intent mBackgroundIntent
+ static final Intent mBackgroundIntent
= new Intent().addFlags(Intent.FLAG_FROM_BACKGROUND);
- private static final IncreasingTimeOrder sIncreasingTimeOrder = new IncreasingTimeOrder();
+ static final IncreasingTimeOrder sIncreasingTimeOrder = new IncreasingTimeOrder();
- private static final boolean WAKEUP_STATS = false;
+ static final boolean WAKEUP_STATS = false;
- private final Context mContext;
+ final LocalLog mLog = new LocalLog(TAG);
- private final LocalLog mLog = new LocalLog(TAG);
+ final Object mLock = new Object();
- private Object mLock = new Object();
-
- private long mNativeData;
+ long mNativeData;
private long mNextWakeup;
private long mNextNonWakeup;
- private int mBroadcastRefCount = 0;
- private PowerManager.WakeLock mWakeLock;
- private ArrayList<InFlight> mInFlight = new ArrayList<InFlight>();
- private final AlarmThread mWaitThread = new AlarmThread();
- private final AlarmHandler mHandler = new AlarmHandler();
- private ClockReceiver mClockReceiver;
+ int mBroadcastRefCount = 0;
+ PowerManager.WakeLock mWakeLock;
+ ArrayList<InFlight> mInFlight = new ArrayList<InFlight>();
+ final AlarmHandler mHandler = new AlarmHandler();
+ ClockReceiver mClockReceiver;
private UninstallReceiver mUninstallReceiver;
- private final ResultReceiver mResultReceiver = new ResultReceiver();
- private final PendingIntent mTimeTickSender;
- private final PendingIntent mDateChangeSender;
+ final ResultReceiver mResultReceiver = new ResultReceiver();
+ PendingIntent mTimeTickSender;
+ PendingIntent mDateChangeSender;
class WakeupEvent {
public long when;
@@ -125,8 +123,8 @@
}
}
- private final LinkedList<WakeupEvent> mRecentWakeups = new LinkedList<WakeupEvent>();
- private final long RECENT_WAKEUP_PERIOD = 1000L * 60 * 60 * 24; // one day
+ final LinkedList<WakeupEvent> mRecentWakeups = new LinkedList<WakeupEvent>();
+ final long RECENT_WAKEUP_PERIOD = 1000L * 60 * 60 * 24; // one day
static final class Batch {
long start; // These endpoints are always in ELAPSED
@@ -317,9 +315,9 @@
}
// minimum recurrence period or alarm futurity for us to be able to fuzz it
- private static final long MIN_FUZZABLE_INTERVAL = 10000;
- private static final BatchTimeOrder sBatchOrder = new BatchTimeOrder();
- private final ArrayList<Batch> mAlarmBatches = new ArrayList<Batch>();
+ static final long MIN_FUZZABLE_INTERVAL = 10000;
+ static final BatchTimeOrder sBatchOrder = new BatchTimeOrder();
+ final ArrayList<Batch> mAlarmBatches = new ArrayList<Batch>();
static long convertToElapsed(long when, int type) {
final boolean isRtc = (type == RTC || type == RTC_WAKEUP);
@@ -403,7 +401,7 @@
}
}
- private static final class InFlight extends Intent {
+ static final class InFlight extends Intent {
final PendingIntent mPendingIntent;
final WorkSource mWorkSource;
final Pair<String, ComponentName> mTarget;
@@ -427,7 +425,7 @@
}
}
- private static final class FilterStats {
+ static final class FilterStats {
final BroadcastStats mBroadcastStats;
final Pair<String, ComponentName> mTarget;
@@ -443,7 +441,7 @@
}
}
- private static final class BroadcastStats {
+ static final class BroadcastStats {
final String mPackageName;
long aggregateTime;
@@ -459,47 +457,48 @@
}
}
- private final HashMap<String, BroadcastStats> mBroadcastStats
+ final HashMap<String, BroadcastStats> mBroadcastStats
= new HashMap<String, BroadcastStats>();
- public AlarmManagerService(Context context) {
- mContext = context;
+ @Override
+ public void onStart() {
mNativeData = init();
mNextWakeup = mNextNonWakeup = 0;
// We have to set current TimeZone info to kernel
// because kernel doesn't keep this after reboot
- String tz = SystemProperties.get(TIMEZONE_PROPERTY);
- if (tz != null) {
- setTimeZone(tz);
- }
+ setTimeZoneImpl(SystemProperties.get(TIMEZONE_PROPERTY));
- PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+ PowerManager pm = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
- mTimeTickSender = PendingIntent.getBroadcastAsUser(context, 0,
+ mTimeTickSender = PendingIntent.getBroadcastAsUser(getContext(), 0,
new Intent(Intent.ACTION_TIME_TICK).addFlags(
Intent.FLAG_RECEIVER_REGISTERED_ONLY
| Intent.FLAG_RECEIVER_FOREGROUND), 0,
UserHandle.ALL);
Intent intent = new Intent(Intent.ACTION_DATE_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
- mDateChangeSender = PendingIntent.getBroadcastAsUser(context, 0, intent,
+ mDateChangeSender = PendingIntent.getBroadcastAsUser(getContext(), 0, intent,
Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT, UserHandle.ALL);
// now that we have initied the driver schedule the alarm
- mClockReceiver= new ClockReceiver();
+ mClockReceiver = new ClockReceiver();
mClockReceiver.scheduleTimeTickEvent();
mClockReceiver.scheduleDateChangedEvent();
mUninstallReceiver = new UninstallReceiver();
if (mNativeData != 0) {
- mWaitThread.start();
+ AlarmThread waitThread = new AlarmThread();
+ waitThread.start();
} else {
Slog.w(TAG, "Failed to open alarm driver. Falling back to a handler.");
}
+
+ publishBinderService(Context.ALARM_SERVICE, mService);
}
-
+
+ @Override
protected void finalize() throws Throwable {
try {
close(mNativeData);
@@ -508,19 +507,51 @@
}
}
- @Override
- public void set(int type, long triggerAtTime, long windowLength, long interval,
- PendingIntent operation, WorkSource workSource) {
- if (workSource != null) {
- mContext.enforceCallingPermission(
- android.Manifest.permission.UPDATE_DEVICE_STATS,
- "AlarmManager.set");
+ void setTimeZoneImpl(String tz) {
+ if (TextUtils.isEmpty(tz)) {
+ return;
}
- set(type, triggerAtTime, windowLength, interval, operation, false, workSource);
+ TimeZone zone = TimeZone.getTimeZone(tz);
+ // Prevent reentrant calls from stepping on each other when writing
+ // the time zone property
+ boolean timeZoneWasChanged = false;
+ synchronized (this) {
+ String current = SystemProperties.get(TIMEZONE_PROPERTY);
+ if (current == null || !current.equals(zone.getID())) {
+ if (localLOGV) {
+ Slog.v(TAG, "timezone changed: " + current + ", new=" + zone.getID());
+ }
+ timeZoneWasChanged = true;
+ SystemProperties.set(TIMEZONE_PROPERTY, zone.getID());
+ }
+
+ // Update the kernel timezone information
+ // Kernel tracks time offsets as 'minutes west of GMT'
+ int gmtOffset = zone.getOffset(System.currentTimeMillis());
+ setKernelTimezone(mNativeData, -(gmtOffset / 60000));
+ }
+
+ TimeZone.setDefault(null);
+
+ if (timeZoneWasChanged) {
+ Intent intent = new Intent(Intent.ACTION_TIMEZONE_CHANGED);
+ intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+ intent.putExtra("time-zone", zone.getID());
+ getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
+ }
}
- public void set(int type, long triggerAtTime, long windowLength, long interval,
+ void removeImpl(PendingIntent operation) {
+ if (operation == null) {
+ return;
+ }
+ synchronized (mLock) {
+ removeLocked(operation);
+ }
+ }
+
+ void setImpl(int type, long triggerAtTime, long windowLength, long interval,
PendingIntent operation, boolean isStandalone, WorkSource workSource) {
if (operation == null) {
Slog.w(TAG, "set/setRepeating ignored because there is no intent");
@@ -606,231 +637,64 @@
rescheduleKernelAlarmsLocked();
}
- private void logBatchesLocked() {
- ByteArrayOutputStream bs = new ByteArrayOutputStream(2048);
- PrintWriter pw = new PrintWriter(bs);
- final long nowRTC = System.currentTimeMillis();
- final long nowELAPSED = SystemClock.elapsedRealtime();
- final int NZ = mAlarmBatches.size();
- for (int iz = 0; iz < NZ; iz++) {
- Batch bz = mAlarmBatches.get(iz);
- pw.append("Batch "); pw.print(iz); pw.append(": "); pw.println(bz);
- dumpAlarmList(pw, bz.alarms, " ", nowELAPSED, nowRTC);
- pw.flush();
- Slog.v(TAG, bs.toString());
- bs.reset();
- }
- }
-
- private boolean validateConsistencyLocked() {
- if (DEBUG_VALIDATE) {
- long lastTime = Long.MIN_VALUE;
- final int N = mAlarmBatches.size();
- for (int i = 0; i < N; i++) {
- Batch b = mAlarmBatches.get(i);
- if (b.start >= lastTime) {
- // duplicate start times are okay because of standalone batches
- lastTime = b.start;
- } else {
- Slog.e(TAG, "CONSISTENCY FAILURE: Batch " + i + " is out of order");
- logBatchesLocked();
- return false;
- }
- }
- }
- return true;
- }
-
- private Batch findFirstWakeupBatchLocked() {
- final int N = mAlarmBatches.size();
- for (int i = 0; i < N; i++) {
- Batch b = mAlarmBatches.get(i);
- if (b.hasWakeups()) {
- return b;
- }
- }
- return null;
- }
-
- private void rescheduleKernelAlarmsLocked() {
- // Schedule the next upcoming wakeup alarm. If there is a deliverable batch
- // prior to that which contains no wakeups, we schedule that as well.
- if (mAlarmBatches.size() > 0) {
- final Batch firstWakeup = findFirstWakeupBatchLocked();
- final Batch firstBatch = mAlarmBatches.get(0);
- if (firstWakeup != null && mNextWakeup != firstWakeup.start) {
- mNextWakeup = firstWakeup.start;
- setLocked(ELAPSED_REALTIME_WAKEUP, firstWakeup.start);
- }
- if (firstBatch != firstWakeup && mNextNonWakeup != firstBatch.start) {
- mNextNonWakeup = firstBatch.start;
- setLocked(ELAPSED_REALTIME, firstBatch.start);
- }
- }
- }
-
- public void setTime(long millis) {
- mContext.enforceCallingOrSelfPermission(
- "android.permission.SET_TIME",
- "setTime");
-
- SystemClock.setCurrentTimeMillis(millis);
- }
-
- public void setTimeZone(String tz) {
- mContext.enforceCallingOrSelfPermission(
- "android.permission.SET_TIME_ZONE",
- "setTimeZone");
-
- long oldId = Binder.clearCallingIdentity();
- try {
- if (TextUtils.isEmpty(tz)) return;
- TimeZone zone = TimeZone.getTimeZone(tz);
- // Prevent reentrant calls from stepping on each other when writing
- // the time zone property
- boolean timeZoneWasChanged = false;
- synchronized (this) {
- String current = SystemProperties.get(TIMEZONE_PROPERTY);
- if (current == null || !current.equals(zone.getID())) {
- if (localLOGV) {
- Slog.v(TAG, "timezone changed: " + current + ", new=" + zone.getID());
- }
- timeZoneWasChanged = true;
- SystemProperties.set(TIMEZONE_PROPERTY, zone.getID());
- }
-
- // Update the kernel timezone information
- // Kernel tracks time offsets as 'minutes west of GMT'
- int gmtOffset = zone.getOffset(System.currentTimeMillis());
- setKernelTimezone(mNativeData, -(gmtOffset / 60000));
+ private final IBinder mService = new IAlarmManager.Stub() {
+ @Override
+ public void set(int type, long triggerAtTime, long windowLength, long interval,
+ PendingIntent operation, WorkSource workSource) {
+ if (workSource != null) {
+ getContext().enforceCallingPermission(
+ android.Manifest.permission.UPDATE_DEVICE_STATS,
+ "AlarmManager.set");
}
- TimeZone.setDefault(null);
+ setImpl(type, triggerAtTime, windowLength, interval, operation,
+ false, workSource);
+ }
- if (timeZoneWasChanged) {
- Intent intent = new Intent(Intent.ACTION_TIMEZONE_CHANGED);
- intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
- intent.putExtra("time-zone", zone.getID());
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
- }
- } finally {
- Binder.restoreCallingIdentity(oldId);
+ @Override
+ public void setTime(long millis) {
+ getContext().enforceCallingOrSelfPermission(
+ "android.permission.SET_TIME",
+ "setTime");
+
+ SystemClock.setCurrentTimeMillis(millis);
}
- }
-
- public void remove(PendingIntent operation) {
- if (operation == null) {
- return;
- }
- synchronized (mLock) {
- removeLocked(operation);
- }
- }
-
- public void removeLocked(PendingIntent operation) {
- boolean didRemove = false;
- for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
- Batch b = mAlarmBatches.get(i);
- didRemove |= b.remove(operation);
- if (b.size() == 0) {
- mAlarmBatches.remove(i);
+
+ @Override
+ public void setTimeZone(String tz) {
+ getContext().enforceCallingOrSelfPermission(
+ "android.permission.SET_TIME_ZONE",
+ "setTimeZone");
+
+ final long oldId = Binder.clearCallingIdentity();
+ try {
+ setTimeZoneImpl(tz);
+ } finally {
+ Binder.restoreCallingIdentity(oldId);
}
}
- if (didRemove) {
- if (DEBUG_BATCH) {
- Slog.v(TAG, "remove(operation) changed bounds; rebatching");
- }
- rebatchAllAlarmsLocked(true);
- rescheduleKernelAlarmsLocked();
- }
- }
+ @Override
+ public void remove(PendingIntent operation) {
+ removeImpl(operation);
- public void removeLocked(String packageName) {
- boolean didRemove = false;
- for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
- Batch b = mAlarmBatches.get(i);
- didRemove |= b.remove(packageName);
- if (b.size() == 0) {
- mAlarmBatches.remove(i);
- }
}
- if (didRemove) {
- if (DEBUG_BATCH) {
- Slog.v(TAG, "remove(package) changed bounds; rebatching");
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+ != PackageManager.PERMISSION_GRANTED) {
+ pw.println("Permission Denial: can't dump AlarmManager from from pid="
+ + Binder.getCallingPid()
+ + ", uid=" + Binder.getCallingUid());
+ return;
}
- rebatchAllAlarmsLocked(true);
- rescheduleKernelAlarmsLocked();
- }
- }
- public void removeUserLocked(int userHandle) {
- boolean didRemove = false;
- for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
- Batch b = mAlarmBatches.get(i);
- didRemove |= b.remove(userHandle);
- if (b.size() == 0) {
- mAlarmBatches.remove(i);
- }
+ dumpImpl(pw);
}
+ };
- if (didRemove) {
- if (DEBUG_BATCH) {
- Slog.v(TAG, "remove(user) changed bounds; rebatching");
- }
- rebatchAllAlarmsLocked(true);
- rescheduleKernelAlarmsLocked();
- }
- }
-
- public boolean lookForPackageLocked(String packageName) {
- for (int i = 0; i < mAlarmBatches.size(); i++) {
- Batch b = mAlarmBatches.get(i);
- if (b.hasPackage(packageName)) {
- return true;
- }
- }
- return false;
- }
-
- private void setLocked(int type, long when)
- {
- if (mNativeData != 0)
- {
- // The kernel never triggers alarms with negative wakeup times
- // so we ensure they are positive.
- long alarmSeconds, alarmNanoseconds;
- if (when < 0) {
- alarmSeconds = 0;
- alarmNanoseconds = 0;
- } else {
- alarmSeconds = when / 1000;
- alarmNanoseconds = (when % 1000) * 1000 * 1000;
- }
-
- set(mNativeData, type, alarmSeconds, alarmNanoseconds);
- }
- else
- {
- Message msg = Message.obtain();
- msg.what = ALARM_EVENT;
-
- mHandler.removeMessages(ALARM_EVENT);
- mHandler.sendMessageAtTime(msg, when);
- }
- }
-
- @Override
- protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump AlarmManager from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
-
+ void dumpImpl(PrintWriter pw) {
synchronized (mLock) {
pw.println("Current Alarm Manager state:");
final long nowRTC = System.currentTimeMillis();
@@ -980,6 +844,159 @@
}
}
+ private void logBatchesLocked() {
+ ByteArrayOutputStream bs = new ByteArrayOutputStream(2048);
+ PrintWriter pw = new PrintWriter(bs);
+ final long nowRTC = System.currentTimeMillis();
+ final long nowELAPSED = SystemClock.elapsedRealtime();
+ final int NZ = mAlarmBatches.size();
+ for (int iz = 0; iz < NZ; iz++) {
+ Batch bz = mAlarmBatches.get(iz);
+ pw.append("Batch "); pw.print(iz); pw.append(": "); pw.println(bz);
+ dumpAlarmList(pw, bz.alarms, " ", nowELAPSED, nowRTC);
+ pw.flush();
+ Slog.v(TAG, bs.toString());
+ bs.reset();
+ }
+ }
+
+ private boolean validateConsistencyLocked() {
+ if (DEBUG_VALIDATE) {
+ long lastTime = Long.MIN_VALUE;
+ final int N = mAlarmBatches.size();
+ for (int i = 0; i < N; i++) {
+ Batch b = mAlarmBatches.get(i);
+ if (b.start >= lastTime) {
+ // duplicate start times are okay because of standalone batches
+ lastTime = b.start;
+ } else {
+ Slog.e(TAG, "CONSISTENCY FAILURE: Batch " + i + " is out of order");
+ logBatchesLocked();
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private Batch findFirstWakeupBatchLocked() {
+ final int N = mAlarmBatches.size();
+ for (int i = 0; i < N; i++) {
+ Batch b = mAlarmBatches.get(i);
+ if (b.hasWakeups()) {
+ return b;
+ }
+ }
+ return null;
+ }
+
+ void rescheduleKernelAlarmsLocked() {
+ // Schedule the next upcoming wakeup alarm. If there is a deliverable batch
+ // prior to that which contains no wakeups, we schedule that as well.
+ if (mAlarmBatches.size() > 0) {
+ final Batch firstWakeup = findFirstWakeupBatchLocked();
+ final Batch firstBatch = mAlarmBatches.get(0);
+ if (firstWakeup != null && mNextWakeup != firstWakeup.start) {
+ mNextWakeup = firstWakeup.start;
+ setLocked(ELAPSED_REALTIME_WAKEUP, firstWakeup.start);
+ }
+ if (firstBatch != firstWakeup && mNextNonWakeup != firstBatch.start) {
+ mNextNonWakeup = firstBatch.start;
+ setLocked(ELAPSED_REALTIME, firstBatch.start);
+ }
+ }
+ }
+
+ private void removeLocked(PendingIntent operation) {
+ boolean didRemove = false;
+ for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
+ Batch b = mAlarmBatches.get(i);
+ didRemove |= b.remove(operation);
+ if (b.size() == 0) {
+ mAlarmBatches.remove(i);
+ }
+ }
+
+ if (didRemove) {
+ if (DEBUG_BATCH) {
+ Slog.v(TAG, "remove(operation) changed bounds; rebatching");
+ }
+ rebatchAllAlarmsLocked(true);
+ rescheduleKernelAlarmsLocked();
+ }
+ }
+
+ void removeLocked(String packageName) {
+ boolean didRemove = false;
+ for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
+ Batch b = mAlarmBatches.get(i);
+ didRemove |= b.remove(packageName);
+ if (b.size() == 0) {
+ mAlarmBatches.remove(i);
+ }
+ }
+
+ if (didRemove) {
+ if (DEBUG_BATCH) {
+ Slog.v(TAG, "remove(package) changed bounds; rebatching");
+ }
+ rebatchAllAlarmsLocked(true);
+ rescheduleKernelAlarmsLocked();
+ }
+ }
+
+ void removeUserLocked(int userHandle) {
+ boolean didRemove = false;
+ for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
+ Batch b = mAlarmBatches.get(i);
+ didRemove |= b.remove(userHandle);
+ if (b.size() == 0) {
+ mAlarmBatches.remove(i);
+ }
+ }
+
+ if (didRemove) {
+ if (DEBUG_BATCH) {
+ Slog.v(TAG, "remove(user) changed bounds; rebatching");
+ }
+ rebatchAllAlarmsLocked(true);
+ rescheduleKernelAlarmsLocked();
+ }
+ }
+
+ boolean lookForPackageLocked(String packageName) {
+ for (int i = 0; i < mAlarmBatches.size(); i++) {
+ Batch b = mAlarmBatches.get(i);
+ if (b.hasPackage(packageName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void setLocked(int type, long when) {
+ if (mNativeData != 0) {
+ // The kernel never triggers alarms with negative wakeup times
+ // so we ensure they are positive.
+ long alarmSeconds, alarmNanoseconds;
+ if (when < 0) {
+ alarmSeconds = 0;
+ alarmNanoseconds = 0;
+ } else {
+ alarmSeconds = when / 1000;
+ alarmNanoseconds = (when % 1000) * 1000 * 1000;
+ }
+
+ set(mNativeData, type, alarmSeconds, alarmNanoseconds);
+ } else {
+ Message msg = Message.obtain();
+ msg.what = ALARM_EVENT;
+
+ mHandler.removeMessages(ALARM_EVENT);
+ mHandler.sendMessageAtTime(msg, when);
+ }
+ }
+
private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list,
String prefix, String label, long now) {
for (int i=list.size()-1; i>=0; i--) {
@@ -1020,7 +1037,7 @@
private native int waitForAlarm(long nativeData);
private native int setKernelTimezone(long nativeData, int minuteswest);
- private void triggerAlarmsLocked(ArrayList<Alarm> triggerList, long nowELAPSED, long nowRTC) {
+ void triggerAlarmsLocked(ArrayList<Alarm> triggerList, long nowELAPSED, long nowRTC) {
// batches are temporally sorted, so we need only pull from the
// start of the list until we either empty it or hit a batch
// that is not yet deliverable
@@ -1166,13 +1183,13 @@
if (DEBUG_BATCH) {
Slog.v(TAG, "Time changed notification from kernel; rebatching");
}
- remove(mTimeTickSender);
+ removeImpl(mTimeTickSender);
rebatchAllAlarms();
mClockReceiver.scheduleTimeTickEvent();
Intent intent = new Intent(Intent.ACTION_TIME_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
| Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
}
synchronized (mLock) {
@@ -1206,7 +1223,7 @@
Alarm alarm = triggerList.get(i);
try {
if (localLOGV) Slog.v(TAG, "sending alarm " + alarm);
- alarm.operation.send(mContext, 0,
+ alarm.operation.send(getContext(), 0,
mBackgroundIntent.putExtra(
Intent.EXTRA_ALARM_COUNT, alarm.count),
mResultReceiver, mHandler);
@@ -1248,7 +1265,7 @@
if (alarm.repeatInterval > 0) {
// This IntentSender is no longer valid, but this
// is a repeating alarm, so toss the hoser.
- remove(alarm.operation);
+ removeImpl(alarm.operation);
}
} catch (RuntimeException e) {
Slog.w(TAG, "Failure sending alarm.", e);
@@ -1310,7 +1327,7 @@
if (alarm.repeatInterval > 0) {
// This IntentSender is no longer valid, but this
// is a repeating alarm, so toss the hoser.
- remove(alarm.operation);
+ removeImpl(alarm.operation);
}
}
}
@@ -1323,7 +1340,7 @@
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_TIME_TICK);
filter.addAction(Intent.ACTION_DATE_CHANGED);
- mContext.registerReceiver(this, filter);
+ getContext().registerReceiver(this, filter);
}
@Override
@@ -1354,7 +1371,7 @@
final long tickEventDelay = nextTime - currentTime;
final WorkSource workSource = null; // Let system take blame for time tick events.
- set(ELAPSED_REALTIME, SystemClock.elapsedRealtime() + tickEventDelay, 0,
+ setImpl(ELAPSED_REALTIME, SystemClock.elapsedRealtime() + tickEventDelay, 0,
0, mTimeTickSender, true, workSource);
}
@@ -1368,7 +1385,7 @@
calendar.add(Calendar.DAY_OF_MONTH, 1);
final WorkSource workSource = null; // Let system take blame for date change events.
- set(RTC, calendar.getTimeInMillis(), 0, 0, mDateChangeSender, true, workSource);
+ setImpl(RTC, calendar.getTimeInMillis(), 0, 0, mDateChangeSender, true, workSource);
}
}
@@ -1379,12 +1396,12 @@
filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
filter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
filter.addDataScheme("package");
- mContext.registerReceiver(this, filter);
+ getContext().registerReceiver(this, filter);
// Register for events related to sdcard installation.
IntentFilter sdFilter = new IntentFilter();
sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
sdFilter.addAction(Intent.ACTION_USER_STOPPED);
- mContext.registerReceiver(this, sdFilter);
+ getContext().registerReceiver(this, sdFilter);
}
@Override
diff --git a/services/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
similarity index 99%
rename from services/java/com/android/server/AppOpsService.java
rename to services/core/java/com/android/server/AppOpsService.java
index a1a0d47..e5615c0 100644
--- a/services/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -186,9 +186,9 @@
}
}
- public AppOpsService(File storagePath) {
+ public AppOpsService(File storagePath, Handler handler) {
mFile = new AtomicFile(storagePath);
- mHandler = new Handler();
+ mHandler = handler;
readState();
}
diff --git a/services/java/com/android/server/AssetAtlasService.java b/services/core/java/com/android/server/AssetAtlasService.java
similarity index 100%
rename from services/java/com/android/server/AssetAtlasService.java
rename to services/core/java/com/android/server/AssetAtlasService.java
diff --git a/services/java/com/android/server/AttributeCache.java b/services/core/java/com/android/server/AttributeCache.java
similarity index 100%
rename from services/java/com/android/server/AttributeCache.java
rename to services/core/java/com/android/server/AttributeCache.java
diff --git a/services/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
similarity index 97%
rename from services/java/com/android/server/BatteryService.java
rename to services/core/java/com/android/server/BatteryService.java
index 5f3f894..cc9055d 100644
--- a/services/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -19,6 +19,8 @@
import android.os.BatteryStats;
import com.android.internal.app.IBatteryStats;
import com.android.server.am.BatteryStatsService;
+import com.android.server.lights.Light;
+import com.android.server.lights.LightsManager;
import android.app.ActivityManagerNative;
import android.content.ContentResolver;
@@ -134,13 +136,10 @@
private boolean mSentLowBatteryBroadcast = false;
- private BatteryListener mBatteryPropertiesListener;
- private IBatteryPropertiesRegistrar mBatteryPropertiesRegistrar;
-
- public BatteryService(Context context, LightsService lights) {
+ public BatteryService(Context context, LightsManager lightsManager) {
mContext = context;
mHandler = new Handler(true /*async*/);
- mLed = new Led(context, lights);
+ mLed = new Led(context, lightsManager);
mBatteryStats = BatteryStatsService.getService();
mCriticalBatteryLevel = mContext.getResources().getInteger(
@@ -158,13 +157,11 @@
"DEVPATH=/devices/virtual/switch/invalid_charger");
}
- mBatteryPropertiesListener = new BatteryListener();
-
IBinder b = ServiceManager.getService("batterypropreg");
- mBatteryPropertiesRegistrar = IBatteryPropertiesRegistrar.Stub.asInterface(b);
-
+ final IBatteryPropertiesRegistrar batteryPropertiesRegistrar =
+ IBatteryPropertiesRegistrar.Stub.asInterface(b);
try {
- mBatteryPropertiesRegistrar.registerListener(mBatteryPropertiesListener);
+ batteryPropertiesRegistrar.registerListener(new BatteryListener());
} catch (RemoteException e) {
// Should never happen.
}
@@ -688,7 +685,7 @@
};
private final class Led {
- private final LightsService.Light mBatteryLight;
+ private final Light mBatteryLight;
private final int mBatteryLowARGB;
private final int mBatteryMediumARGB;
@@ -696,8 +693,8 @@
private final int mBatteryLedOn;
private final int mBatteryLedOff;
- public Led(Context context, LightsService lights) {
- mBatteryLight = lights.getLight(LightsService.LIGHT_ID_BATTERY);
+ public Led(Context context, LightsManager lights) {
+ mBatteryLight = lights.getLight(LightsManager.LIGHT_ID_BATTERY);
mBatteryLowARGB = context.getResources().getInteger(
com.android.internal.R.integer.config_notificationsBatteryLowARGB);
@@ -723,7 +720,7 @@
mBatteryLight.setColor(mBatteryLowARGB);
} else {
// Flash red when battery is low and not charging
- mBatteryLight.setFlashing(mBatteryLowARGB, LightsService.LIGHT_FLASH_TIMED,
+ mBatteryLight.setFlashing(mBatteryLowARGB, Light.LIGHT_FLASH_TIMED,
mBatteryLedOn, mBatteryLedOff);
}
} else if (status == BatteryManager.BATTERY_STATUS_CHARGING
@@ -743,8 +740,14 @@
}
private final class BatteryListener extends IBatteryPropertiesListener.Stub {
+ @Override
public void batteryPropertiesChanged(BatteryProperties props) {
- BatteryService.this.update(props);
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ BatteryService.this.update(props);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
}
}
diff --git a/services/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
similarity index 100%
rename from services/java/com/android/server/BluetoothManagerService.java
rename to services/core/java/com/android/server/BluetoothManagerService.java
diff --git a/services/java/com/android/server/BootReceiver.java b/services/core/java/com/android/server/BootReceiver.java
similarity index 100%
rename from services/java/com/android/server/BootReceiver.java
rename to services/core/java/com/android/server/BootReceiver.java
diff --git a/services/java/com/android/server/BrickReceiver.java b/services/core/java/com/android/server/BrickReceiver.java
similarity index 100%
rename from services/java/com/android/server/BrickReceiver.java
rename to services/core/java/com/android/server/BrickReceiver.java
diff --git a/services/java/com/android/server/CertBlacklister.java b/services/core/java/com/android/server/CertBlacklister.java
similarity index 100%
rename from services/java/com/android/server/CertBlacklister.java
rename to services/core/java/com/android/server/CertBlacklister.java
diff --git a/services/java/com/android/server/CommonTimeManagementService.java b/services/core/java/com/android/server/CommonTimeManagementService.java
similarity index 100%
rename from services/java/com/android/server/CommonTimeManagementService.java
rename to services/core/java/com/android/server/CommonTimeManagementService.java
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
similarity index 100%
rename from services/java/com/android/server/ConnectivityService.java
rename to services/core/java/com/android/server/ConnectivityService.java
diff --git a/services/java/com/android/server/ConsumerIrService.java b/services/core/java/com/android/server/ConsumerIrService.java
similarity index 100%
rename from services/java/com/android/server/ConsumerIrService.java
rename to services/core/java/com/android/server/ConsumerIrService.java
diff --git a/services/java/com/android/server/CountryDetectorService.java b/services/core/java/com/android/server/CountryDetectorService.java
similarity index 100%
rename from services/java/com/android/server/CountryDetectorService.java
rename to services/core/java/com/android/server/CountryDetectorService.java
diff --git a/services/java/com/android/server/DiskStatsService.java b/services/core/java/com/android/server/DiskStatsService.java
similarity index 100%
rename from services/java/com/android/server/DiskStatsService.java
rename to services/core/java/com/android/server/DiskStatsService.java
diff --git a/services/core/java/com/android/server/DisplayThread.java b/services/core/java/com/android/server/DisplayThread.java
new file mode 100644
index 0000000..528ba0a
--- /dev/null
+++ b/services/core/java/com/android/server/DisplayThread.java
@@ -0,0 +1,56 @@
+/*
+ * 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.server;
+
+import android.os.Handler;
+
+/**
+ * Shared singleton foreground thread for the system. This is a thread for
+ * operations that affect what's on the display, which needs to have a minimum
+ * of latency. This thread should pretty much only be used by the WindowManager,
+ * DisplayManager, and InputManager to perform quick operations in real time.
+ */
+public final class DisplayThread extends ServiceThread {
+ private static DisplayThread sInstance;
+ private static Handler sHandler;
+
+ private DisplayThread() {
+ super("android.display", android.os.Process.THREAD_PRIORITY_DISPLAY, false /*allowIo*/);
+ }
+
+ private static void ensureThreadLocked() {
+ if (sInstance == null) {
+ sInstance = new DisplayThread();
+ sInstance.start();
+ sHandler = new Handler(sInstance.getLooper());
+ }
+ }
+
+ public static DisplayThread get() {
+ synchronized (UiThread.class) {
+ ensureThreadLocked();
+ return sInstance;
+ }
+ }
+
+ public static Handler getHandler() {
+ synchronized (UiThread.class) {
+ ensureThreadLocked();
+ return sHandler;
+ }
+ }
+}
diff --git a/services/java/com/android/server/DockObserver.java b/services/core/java/com/android/server/DockObserver.java
similarity index 100%
rename from services/java/com/android/server/DockObserver.java
rename to services/core/java/com/android/server/DockObserver.java
diff --git a/services/java/com/android/server/DropBoxManagerService.java b/services/core/java/com/android/server/DropBoxManagerService.java
similarity index 100%
rename from services/java/com/android/server/DropBoxManagerService.java
rename to services/core/java/com/android/server/DropBoxManagerService.java
diff --git a/services/java/com/android/server/EntropyMixer.java b/services/core/java/com/android/server/EntropyMixer.java
similarity index 100%
rename from services/java/com/android/server/EntropyMixer.java
rename to services/core/java/com/android/server/EntropyMixer.java
diff --git a/services/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
similarity index 100%
rename from services/java/com/android/server/EventLogTags.logtags
rename to services/core/java/com/android/server/EventLogTags.logtags
diff --git a/services/java/com/android/server/FgThread.java b/services/core/java/com/android/server/FgThread.java
similarity index 85%
rename from services/java/com/android/server/FgThread.java
rename to services/core/java/com/android/server/FgThread.java
index 3b655f2..03765db 100644
--- a/services/java/com/android/server/FgThread.java
+++ b/services/core/java/com/android/server/FgThread.java
@@ -17,7 +17,6 @@
package com.android.server;
import android.os.Handler;
-import android.os.HandlerThread;
/**
* Shared singleton foreground thread for the system. This is a thread for regular
@@ -27,12 +26,12 @@
* simply being a background priority), which can cause operations scheduled on it
* to be delayed for a user-noticeable amount of time.
*/
-public final class FgThread extends HandlerThread {
+public final class FgThread extends ServiceThread {
private static FgThread sInstance;
private static Handler sHandler;
private FgThread() {
- super("android.fg", android.os.Process.THREAD_PRIORITY_DEFAULT);
+ super("android.fg", android.os.Process.THREAD_PRIORITY_DEFAULT, true /*allowIo*/);
}
private static void ensureThreadLocked() {
@@ -40,12 +39,6 @@
sInstance = new FgThread();
sInstance.start();
sHandler = new Handler(sInstance.getLooper());
- sHandler.post(new Runnable() {
- @Override
- public void run() {
- android.os.Process.setCanSelfBackground(false);
- }
- });
}
}
diff --git a/services/java/com/android/server/INativeDaemonConnectorCallbacks.java b/services/core/java/com/android/server/INativeDaemonConnectorCallbacks.java
similarity index 100%
rename from services/java/com/android/server/INativeDaemonConnectorCallbacks.java
rename to services/core/java/com/android/server/INativeDaemonConnectorCallbacks.java
diff --git a/services/java/com/android/server/IdleMaintenanceService.java b/services/core/java/com/android/server/IdleMaintenanceService.java
similarity index 100%
rename from services/java/com/android/server/IdleMaintenanceService.java
rename to services/core/java/com/android/server/IdleMaintenanceService.java
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
similarity index 99%
rename from services/java/com/android/server/InputMethodManagerService.java
rename to services/core/java/com/android/server/InputMethodManagerService.java
index a996dbd..26424a5 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -28,7 +28,7 @@
import com.android.internal.view.IInputMethodManager;
import com.android.internal.view.IInputMethodSession;
import com.android.internal.view.InputBindResult;
-import com.android.server.EventLogTags;
+import com.android.server.statusbar.StatusBarManagerService;
import com.android.server.wm.WindowManagerService;
import org.xmlpull.v1.XmlPullParser;
diff --git a/services/java/com/android/server/IntentResolver.java b/services/core/java/com/android/server/IntentResolver.java
similarity index 100%
rename from services/java/com/android/server/IntentResolver.java
rename to services/core/java/com/android/server/IntentResolver.java
diff --git a/services/java/com/android/server/IoThread.java b/services/core/java/com/android/server/IoThread.java
similarity index 84%
rename from services/java/com/android/server/IoThread.java
rename to services/core/java/com/android/server/IoThread.java
index 09f2af7..0f29857 100644
--- a/services/java/com/android/server/IoThread.java
+++ b/services/core/java/com/android/server/IoThread.java
@@ -17,19 +17,18 @@
package com.android.server;
import android.os.Handler;
-import android.os.HandlerThread;
/**
* Shared singleton I/O thread for the system. This is a thread for non-background
* service operations that can potential block briefly on network IO operations
* (not waiting for data itself, but communicating with network daemons).
*/
-public final class IoThread extends HandlerThread {
+public final class IoThread extends ServiceThread {
private static IoThread sInstance;
private static Handler sHandler;
private IoThread() {
- super("android.io", android.os.Process.THREAD_PRIORITY_DEFAULT);
+ super("android.io", android.os.Process.THREAD_PRIORITY_DEFAULT, true /*allowIo*/);
}
private static void ensureThreadLocked() {
@@ -37,12 +36,6 @@
sInstance = new IoThread();
sInstance.start();
sHandler = new Handler(sInstance.getLooper());
- sHandler.post(new Runnable() {
- @Override
- public void run() {
- android.os.Process.setCanSelfBackground(false);
- }
- });
}
}
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
similarity index 100%
rename from services/java/com/android/server/LocationManagerService.java
rename to services/core/java/com/android/server/LocationManagerService.java
diff --git a/services/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
similarity index 100%
rename from services/java/com/android/server/LockSettingsService.java
rename to services/core/java/com/android/server/LockSettingsService.java
diff --git a/services/java/com/android/server/MasterClearReceiver.java b/services/core/java/com/android/server/MasterClearReceiver.java
similarity index 100%
rename from services/java/com/android/server/MasterClearReceiver.java
rename to services/core/java/com/android/server/MasterClearReceiver.java
diff --git a/services/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
similarity index 100%
rename from services/java/com/android/server/MountService.java
rename to services/core/java/com/android/server/MountService.java
diff --git a/services/java/com/android/server/NativeDaemonConnector.java b/services/core/java/com/android/server/NativeDaemonConnector.java
similarity index 100%
rename from services/java/com/android/server/NativeDaemonConnector.java
rename to services/core/java/com/android/server/NativeDaemonConnector.java
diff --git a/services/java/com/android/server/NativeDaemonConnectorException.java b/services/core/java/com/android/server/NativeDaemonConnectorException.java
similarity index 100%
rename from services/java/com/android/server/NativeDaemonConnectorException.java
rename to services/core/java/com/android/server/NativeDaemonConnectorException.java
diff --git a/services/java/com/android/server/NativeDaemonEvent.java b/services/core/java/com/android/server/NativeDaemonEvent.java
similarity index 100%
rename from services/java/com/android/server/NativeDaemonEvent.java
rename to services/core/java/com/android/server/NativeDaemonEvent.java
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
similarity index 100%
rename from services/java/com/android/server/NetworkManagementService.java
rename to services/core/java/com/android/server/NetworkManagementService.java
diff --git a/services/java/com/android/server/NetworkTimeUpdateService.java b/services/core/java/com/android/server/NetworkTimeUpdateService.java
similarity index 100%
rename from services/java/com/android/server/NetworkTimeUpdateService.java
rename to services/core/java/com/android/server/NetworkTimeUpdateService.java
diff --git a/services/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java
similarity index 100%
rename from services/java/com/android/server/NsdService.java
rename to services/core/java/com/android/server/NsdService.java
diff --git a/services/java/com/android/server/RandomBlock.java b/services/core/java/com/android/server/RandomBlock.java
similarity index 100%
rename from services/java/com/android/server/RandomBlock.java
rename to services/core/java/com/android/server/RandomBlock.java
diff --git a/services/java/com/android/server/RecognitionManagerService.java b/services/core/java/com/android/server/RecognitionManagerService.java
similarity index 100%
rename from services/java/com/android/server/RecognitionManagerService.java
rename to services/core/java/com/android/server/RecognitionManagerService.java
diff --git a/services/java/com/android/server/SamplingProfilerService.java b/services/core/java/com/android/server/SamplingProfilerService.java
similarity index 100%
rename from services/java/com/android/server/SamplingProfilerService.java
rename to services/core/java/com/android/server/SamplingProfilerService.java
diff --git a/services/java/com/android/server/SerialService.java b/services/core/java/com/android/server/SerialService.java
similarity index 100%
rename from services/java/com/android/server/SerialService.java
rename to services/core/java/com/android/server/SerialService.java
diff --git a/services/core/java/com/android/server/ServiceThread.java b/services/core/java/com/android/server/ServiceThread.java
new file mode 100644
index 0000000..bce64af
--- /dev/null
+++ b/services/core/java/com/android/server/ServiceThread.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+package com.android.server;
+
+import android.os.HandlerThread;
+import android.os.Process;
+import android.os.StrictMode;
+import android.util.Slog;
+
+/**
+ * Special handler thread that we create for system services that require their own loopers.
+ */
+public class ServiceThread extends HandlerThread {
+ private static final String TAG = "ServiceThread";
+
+ private final boolean mAllowIo;
+
+ public ServiceThread(String name, int priority, boolean allowIo) {
+ super(name, priority);
+ mAllowIo = allowIo;
+ }
+
+ @Override
+ public void run() {
+ Process.setCanSelfBackground(false);
+
+ // For debug builds, log event loop stalls to dropbox for analysis.
+ if (!mAllowIo && StrictMode.conditionallyEnableDebugLogging()) {
+ Slog.i(TAG, "Enabled StrictMode logging for " + getName() + " looper.");
+ }
+
+ super.run();
+ }
+}
\ No newline at end of file
diff --git a/services/java/com/android/server/ServiceWatcher.java b/services/core/java/com/android/server/ServiceWatcher.java
similarity index 100%
rename from services/java/com/android/server/ServiceWatcher.java
rename to services/core/java/com/android/server/ServiceWatcher.java
diff --git a/services/java/com/android/server/ShutdownActivity.java b/services/core/java/com/android/server/ShutdownActivity.java
similarity index 100%
rename from services/java/com/android/server/ShutdownActivity.java
rename to services/core/java/com/android/server/ShutdownActivity.java
diff --git a/services/java/com/android/server/SystemServer.java b/services/core/java/com/android/server/SystemServer.java
similarity index 77%
rename from services/java/com/android/server/SystemServer.java
rename to services/core/java/com/android/server/SystemServer.java
index a42cbcf..6a76388 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/core/java/com/android/server/SystemServer.java
@@ -17,6 +17,9 @@
package com.android.server;
import android.app.ActivityManagerNative;
+import android.app.ActivityThread;
+import android.app.IAlarmManager;
+import android.app.INotificationManager;
import android.bluetooth.BluetoothAdapter;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -28,8 +31,10 @@
import android.media.AudioService;
import android.net.wifi.p2p.WifiP2pService;
import android.os.Environment;
+import android.os.FactoryTest;
import android.os.Handler;
-import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.IPowerManager;
import android.os.Looper;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -51,22 +56,30 @@
import com.android.server.accounts.AccountManagerService;
import com.android.server.am.ActivityManagerService;
import com.android.server.am.BatteryStatsService;
+import com.android.server.clipboard.ClipboardService;
import com.android.server.content.ContentService;
import com.android.server.display.DisplayManagerService;
import com.android.server.dreams.DreamManagerService;
import com.android.server.input.InputManagerService;
+import com.android.server.lights.LightsManager;
+import com.android.server.lights.LightsService;
import com.android.server.media.MediaRouterService;
import com.android.server.net.NetworkPolicyManagerService;
import com.android.server.net.NetworkStatsService;
+import com.android.server.notification.NotificationManagerService;
import com.android.server.os.SchedulingPolicyService;
import com.android.server.pm.Installer;
import com.android.server.pm.PackageManagerService;
import com.android.server.pm.UserManagerService;
import com.android.server.power.PowerManagerService;
import com.android.server.power.ShutdownThread;
-import com.android.server.print.PrintManagerService;
import com.android.server.search.SearchManagerService;
+import com.android.server.statusbar.StatusBarManagerService;
+import com.android.server.storage.DeviceStorageMonitorService;
+import com.android.server.twilight.TwilightManager;
+import com.android.server.twilight.TwilightService;
import com.android.server.usb.UsbService;
+import com.android.server.wallpaper.WallpaperManagerService;
import com.android.server.wifi.WifiService;
import com.android.server.wm.WindowManagerService;
@@ -77,62 +90,209 @@
import java.util.Timer;
import java.util.TimerTask;
-class ServerThread {
+public final class SystemServer {
private static final String TAG = "SystemServer";
+
private static final String ENCRYPTING_STATE = "trigger_restart_min_framework";
private static final String ENCRYPTED_STATE = "1";
- ContentResolver mContentResolver;
+ private static final long SNAPSHOT_INTERVAL = 60 * 60 * 1000; // 1hr
- void reportWtf(String msg, Throwable e) {
+ // The earliest supported time. We pick one day into 1970, to
+ // give any timezone code room without going into negative time.
+ private static final long EARLIEST_SUPPORTED_TIME = 86400 * 1000;
+
+ /*
+ * Implementation class names. TODO: Move them to a codegen class or load
+ * them from the build system somehow.
+ */
+ private static final String BACKUP_MANAGER_SERVICE_CLASS =
+ "com.android.server.backup.BackupManagerSystemService";
+ private static final String DEVICE_POLICY_MANAGER_SERVICE_CLASS =
+ "com.android.server.devicepolicy.DevicePolicyManagerSystemService";
+ private static final String APPWIDGET_SERVICE_CLASS =
+ "com.android.server.appwidget.AppWidgetService";
+ private static final String PRINT_MANAGER_SERVICE_CLASS =
+ "com.android.server.print.PrintManagerService";
+
+ private final int mFactoryTestMode;
+ private Timer mProfilerSnapshotTimer;
+
+ private Context mSystemContext;
+ private SystemServiceManager mSystemServiceManager;
+
+ // TODO: remove all of these references by improving dependency resolution and boot phases
+ private Installer mInstaller;
+ private PowerManagerService mPowerManagerService;
+ private ActivityManagerService mActivityManagerService;
+ private DisplayManagerService mDisplayManagerService;
+ private ContentResolver mContentResolver;
+
+ /**
+ * Called to initialize native system services.
+ */
+ private static native void nativeInit();
+
+ /**
+ * The main entry point from zygote.
+ */
+ public static void main(String[] args) {
+ new SystemServer().run();
+ }
+
+ public SystemServer() {
+ mFactoryTestMode = FactoryTest.getMode();
+ }
+
+ private void run() {
+ // If a device's clock is before 1970 (before 0), a lot of
+ // APIs crash dealing with negative numbers, notably
+ // java.io.File#setLastModified, so instead we fake it and
+ // hope that time from cell towers or NTP fixes it shortly.
+ if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
+ Slog.w(TAG, "System clock is before 1970; setting to 1970.");
+ SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
+ }
+
+ // Here we go!
+ Slog.i(TAG, "Entered the Android system server!");
+ EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, SystemClock.uptimeMillis());
+
+ // In case the runtime switched since last boot (such as when
+ // the old runtime was removed in an OTA), set the system
+ // property so that it is in sync. We can't do this in
+ // libnativehelper's JniInvocation::Init code where we already
+ // had to fallback to a different runtime because it is
+ // running as root and we need to be the system user to set
+ // the property. http://b/11463182
+ SystemProperties.set("persist.sys.dalvik.vm.lib", VMRuntime.getRuntime().vmLibrary());
+
+ // Enable the sampling profiler.
+ if (SamplingProfilerIntegration.isEnabled()) {
+ SamplingProfilerIntegration.start();
+ mProfilerSnapshotTimer = new Timer();
+ mProfilerSnapshotTimer.schedule(new TimerTask() {
+ @Override
+ public void run() {
+ SamplingProfilerIntegration.writeSnapshot("system_server", null);
+ }
+ }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);
+ }
+
+ // Mmmmmm... more memory!
+ VMRuntime.getRuntime().clearGrowthLimit();
+
+ // The system server has to run all of the time, so it needs to be
+ // as efficient as possible with its memory usage.
+ VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
+
+ // Within the system server, it is an error to access Environment paths without
+ // explicitly specifying a user.
+ Environment.setUserRequired(true);
+
+ // Ensure binder calls into the system always run at foreground priority.
+ BinderInternal.disableBackgroundScheduling(true);
+
+ // Prepare the main looper thread (this thread).
+ android.os.Process.setThreadPriority(
+ android.os.Process.THREAD_PRIORITY_FOREGROUND);
+ android.os.Process.setCanSelfBackground(false);
+ Looper.prepareMainLooper();
+
+ // Initialize native services.
+ System.loadLibrary("android_servers");
+ nativeInit();
+
+ // Check whether we failed to shut down last time we tried.
+ // This call may not return.
+ performPendingShutdown();
+
+ // Initialize the system context.
+ createSystemContext();
+
+ // Create the system service manager.
+ mSystemServiceManager = new SystemServiceManager(mSystemContext);
+
+ // Start services.
+ try {
+ startBootstrapServices();
+ startCoreServices();
+ startOtherServices();
+ } catch (RuntimeException ex) {
+ Slog.e("System", "******************************************");
+ Slog.e("System", "************ Failure starting system services", ex);
+ throw ex;
+ }
+
+ // For debug builds, log event loop stalls to dropbox for analysis.
+ if (StrictMode.conditionallyEnableDebugLogging()) {
+ Slog.i(TAG, "Enabled StrictMode for system server main thread.");
+ }
+
+ // Loop forever.
+ Looper.loop();
+ throw new RuntimeException("Main thread loop unexpectedly exited");
+ }
+
+ private void reportWtf(String msg, Throwable e) {
Slog.w(TAG, "***********************************************");
Log.wtf(TAG, "BOOT FAILURE " + msg, e);
}
- public void initAndLoop() {
- EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN,
- SystemClock.uptimeMillis());
+ private void performPendingShutdown() {
+ final String shutdownAction = SystemProperties.get(
+ ShutdownThread.SHUTDOWN_ACTION_PROPERTY, "");
+ if (shutdownAction != null && shutdownAction.length() > 0) {
+ boolean reboot = (shutdownAction.charAt(0) == '1');
- Looper.prepareMainLooper();
-
- android.os.Process.setThreadPriority(
- android.os.Process.THREAD_PRIORITY_FOREGROUND);
-
- BinderInternal.disableBackgroundScheduling(true);
- android.os.Process.setCanSelfBackground(false);
-
- // Check whether we failed to shut down last time we tried.
- {
- final String shutdownAction = SystemProperties.get(
- ShutdownThread.SHUTDOWN_ACTION_PROPERTY, "");
- if (shutdownAction != null && shutdownAction.length() > 0) {
- boolean reboot = (shutdownAction.charAt(0) == '1');
-
- final String reason;
- if (shutdownAction.length() > 1) {
- reason = shutdownAction.substring(1, shutdownAction.length());
- } else {
- reason = null;
- }
-
- ShutdownThread.rebootOrShutdown(reboot, reason);
+ final String reason;
+ if (shutdownAction.length() > 1) {
+ reason = shutdownAction.substring(1, shutdownAction.length());
+ } else {
+ reason = null;
}
+
+ ShutdownThread.rebootOrShutdown(reboot, reason);
}
+ }
- String factoryTestStr = SystemProperties.get("ro.factorytest");
- int factoryTest = "".equals(factoryTestStr) ? SystemServer.FACTORY_TEST_OFF
- : Integer.parseInt(factoryTestStr);
- final boolean headless = "1".equals(SystemProperties.get("ro.config.headless", "0"));
+ private void createSystemContext() {
+ ActivityThread activityThread = ActivityThread.systemMain();
+ mSystemContext = activityThread.getSystemContext();
+ mSystemContext.setTheme(android.R.style.Theme_Holo);
+ }
- Installer installer = null;
+ private void startBootstrapServices() {
+ // Wait for installd to finish starting up so that it has a chance to
+ // create critical directories such as /data/user with the appropriate
+ // permissions. We need this to complete before we initialize other services.
+ mInstaller = mSystemServiceManager.startService(Installer.class);
+
+ // Power manager needs to be started early because other services need it.
+ // TODO: The conversion to the new pattern is incomplete. We need to switch
+ // the power manager's dependencies over then we can use boot phases to arrange
+ // initialization order and remove the mPowerManagerService field.
+ mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
+
+ // Activity manager runs the show.
+ mActivityManagerService = mSystemServiceManager.startService(
+ ActivityManagerService.Lifecycle.class).getService();
+ }
+
+ private void startCoreServices() {
+ // Display manager is needed to provide display metrics before package manager
+ // starts up.
+ mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
+ }
+
+ private void startOtherServices() {
+ final Context context = mSystemContext;
AccountManagerService accountManager = null;
ContentService contentService = null;
- LightsService lights = null;
- PowerManagerService power = null;
- DisplayManagerService display = null;
+ LightsManager lights = null;
BatteryService battery = null;
VibratorService vibrator = null;
- AlarmManagerService alarm = null;
+ IAlarmManager alarm = null;
MountService mountService = null;
NetworkManagementService networkManagement = null;
NetworkStatsService networkStats = null;
@@ -142,14 +302,12 @@
WifiService wifi = null;
NsdService serviceDiscovery= null;
IPackageManager pm = null;
- Context context = null;
WindowManagerService wm = null;
BluetoothManagerService bluetooth = null;
DockObserver dock = null;
UsbService usb = null;
SerialService serial = null;
- TwilightService twilight = null;
- UiModeManagerService uiMode = null;
+ TwilightManager twilight = null;
RecognitionManagerService recognition = null;
NetworkTimeUpdateService networkTimeUpdater = null;
CommonTimeManagementService commonTimeMgmtService = null;
@@ -157,48 +315,8 @@
TelephonyRegistry telephonyRegistry = null;
ConsumerIrService consumerIr = null;
- // Create a handler thread just for the window manager to enjoy.
- HandlerThread wmHandlerThread = new HandlerThread("WindowManager");
- wmHandlerThread.start();
- Handler wmHandler = new Handler(wmHandlerThread.getLooper());
- wmHandler.post(new Runnable() {
- @Override
- public void run() {
- //Looper.myLooper().setMessageLogging(new LogPrinter(
- // android.util.Log.DEBUG, TAG, android.util.Log.LOG_ID_SYSTEM));
- android.os.Process.setThreadPriority(
- android.os.Process.THREAD_PRIORITY_DISPLAY);
- android.os.Process.setCanSelfBackground(false);
-
- // For debug builds, log event loop stalls to dropbox for analysis.
- if (StrictMode.conditionallyEnableDebugLogging()) {
- Slog.i(TAG, "Enabled StrictMode logging for WM Looper");
- }
- }
- });
-
- // bootstrap services
boolean onlyCore = false;
boolean firstBoot = false;
- try {
- // Wait for installd to finished starting up so that it has a chance to
- // create critical directories such as /data/user with the appropriate
- // permissions. We need this to complete before we initialize other services.
- Slog.i(TAG, "Waiting for installd to be ready.");
- installer = new Installer();
- installer.ping();
-
- Slog.i(TAG, "Power Manager");
- power = new PowerManagerService();
- ServiceManager.addService(Context.POWER_SERVICE, power);
-
- Slog.i(TAG, "Activity Manager");
- context = ActivityManagerService.main(factoryTest);
- } catch (RuntimeException e) {
- Slog.e("System", "******************************************");
- Slog.e("System", "************ Failure starting bootstrap service", e);
- }
-
boolean disableStorage = SystemProperties.getBoolean("config.disable_storage", false);
boolean disableMedia = SystemProperties.getBoolean("config.disable_media", false);
boolean disableBluetooth = SystemProperties.getBoolean("config.disable_bluetooth", false);
@@ -209,10 +327,6 @@
boolean disableNetwork = SystemProperties.getBoolean("config.disable_network", false);
try {
- Slog.i(TAG, "Display Manager");
- display = new DisplayManagerService(context, wmHandler);
- ServiceManager.addService(Context.DISPLAY_SERVICE, display, true);
-
Slog.i(TAG, "Telephony Registry");
telephonyRegistry = new TelephonyRegistry(context);
ServiceManager.addService("telephony.registry", telephonyRegistry);
@@ -222,10 +336,8 @@
AttributeCache.init(context);
- if (!display.waitForDefaultDisplay()) {
- reportWtf("Timeout waiting for default display to be initialized.",
- new Throwable());
- }
+ // We need the default display before we can initialize the package manager.
+ mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
Slog.i(TAG, "Package Manager");
// Only run "core" apps if we're encrypting the device.
@@ -238,15 +350,15 @@
onlyCore = true;
}
- pm = PackageManagerService.main(context, installer,
- factoryTest != SystemServer.FACTORY_TEST_OFF,
+ pm = PackageManagerService.main(context, mInstaller,
+ mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF,
onlyCore);
try {
firstBoot = pm.isFirstBoot();
} catch (RemoteException e) {
}
- ActivityManagerService.setSystemProcess();
+ mActivityManagerService.setSystemProcess();
Slog.i(TAG, "Entropy Mixer");
ServiceManager.addService("entropy", new EntropyMixer(context));
@@ -269,13 +381,13 @@
Slog.i(TAG, "Content Manager");
contentService = ContentService.main(context,
- factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL);
+ mFactoryTestMode == FactoryTest.FACTORY_TEST_LOW_LEVEL);
Slog.i(TAG, "System Content Providers");
- ActivityManagerService.installSystemProviders();
+ mActivityManagerService.installSystemProviders();
- Slog.i(TAG, "Lights Service");
- lights = new LightsService(context);
+ mSystemServiceManager.startService(LightsService.class);
+ lights = LocalServices.getService(LightsManager.class);
Slog.i(TAG, "Battery Service");
battery = new BatteryService(context, lights);
@@ -285,49 +397,49 @@
vibrator = new VibratorService(context);
ServiceManager.addService("vibrator", vibrator);
+ // TODO: use boot phase
+ // only initialize the power service after we have started the
+ // lights service, content providers and the battery service.
+ mPowerManagerService.init(lights, battery,
+ BatteryStatsService.getService(),
+ mActivityManagerService.getAppOpsService());
+
Slog.i(TAG, "Consumer IR Service");
consumerIr = new ConsumerIrService(context);
ServiceManager.addService(Context.CONSUMER_IR_SERVICE, consumerIr);
- // only initialize the power service after we have started the
- // lights service, content providers and the battery service.
- power.init(context, lights, ActivityManagerService.self(), battery,
- BatteryStatsService.getService(),
- ActivityManagerService.self().getAppOpsService(), display);
-
- Slog.i(TAG, "Alarm Manager");
- alarm = new AlarmManagerService(context);
- ServiceManager.addService(Context.ALARM_SERVICE, alarm);
+ mSystemServiceManager.startService(AlarmManagerService.class);
+ alarm = IAlarmManager.Stub.asInterface(
+ ServiceManager.getService(Context.ALARM_SERVICE));
Slog.i(TAG, "Init Watchdog");
- Watchdog.getInstance().init(context, battery, power, alarm,
- ActivityManagerService.self());
- Watchdog.getInstance().addThread(wmHandler, "WindowManager thread");
+ final Watchdog watchdog = Watchdog.getInstance();
+ watchdog.init(context, mActivityManagerService);
Slog.i(TAG, "Input Manager");
- inputManager = new InputManagerService(context, wmHandler);
+ inputManager = new InputManagerService(context);
Slog.i(TAG, "Window Manager");
- wm = WindowManagerService.main(context, power, display, inputManager,
- wmHandler, factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL,
+ wm = WindowManagerService.main(context, inputManager,
+ mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
!firstBoot, onlyCore);
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
- ActivityManagerService.self().setWindowManager(wm);
+ mActivityManagerService.setWindowManager(wm);
inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
inputManager.start();
- display.setWindowManager(wm);
- display.setInputManager(inputManager);
+ // TODO: Use service dependencies instead.
+ mDisplayManagerService.windowManagerAndInputReady();
// Skip Bluetooth if we have an emulator kernel
// TODO: Use a more reliable check to see if this product should
// support Bluetooth - see bug 988521
if (SystemProperties.get("ro.kernel.qemu").equals("1")) {
Slog.i(TAG, "No Bluetooh Service (emulator)");
- } else if (factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
+ } else if (mFactoryTestMode == FactoryTest.FACTORY_TEST_LOW_LEVEL) {
Slog.i(TAG, "No Bluetooth Service (factory test)");
} else if (!context.getPackageManager().hasSystemFeature
(PackageManager.FEATURE_BLUETOOTH)) {
@@ -344,11 +456,9 @@
Slog.e("System", "************ Failure starting core service", e);
}
- DevicePolicyManagerService devicePolicy = null;
StatusBarManagerService statusBar = null;
+ INotificationManager notification = null;
InputMethodManagerService imm = null;
- AppWidgetService appWidget = null;
- NotificationManagerService notification = null;
WallpaperManagerService wallpaper = null;
LocationManagerService location = null;
CountryDetectorService countryDetector = null;
@@ -356,11 +466,10 @@
LockSettingsService lockSettings = null;
DreamManagerService dreamy = null;
AssetAtlasService atlas = null;
- PrintManagerService printManager = null;
MediaRouterService mediaRouter = null;
// Bring up services needed for UI.
- if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
+ if (mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
//if (!disableNonCoreServices) { // TODO: View depends on these; mock them?
if (true) {
try {
@@ -397,11 +506,11 @@
ActivityManagerNative.getDefault().showBootMessage(
context.getResources().getText(
com.android.internal.R.string.android_upgrading_starting_apps),
- false);
+ false);
} catch (RemoteException e) {
}
- if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
+ if (mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
if (!disableStorage &&
!"0".equals(SystemProperties.get("system_init.startmountservice"))) {
try {
@@ -428,8 +537,7 @@
try {
Slog.i(TAG, "Device Policy");
- devicePolicy = new DevicePolicyManagerService(context);
- ServiceManager.addService(Context.DEVICE_POLICY_SERVICE, devicePolicy);
+ mSystemServiceManager.startServiceIfExists(DEVICE_POLICY_MANAGER_SERVICE_CLASS);
} catch (Throwable e) {
reportWtf("starting DevicePolicyService", e);
}
@@ -487,7 +595,8 @@
try {
Slog.i(TAG, "NetworkPolicy Service");
networkPolicy = new NetworkPolicyManagerService(
- context, ActivityManagerService.self(), power,
+ context, mActivityManagerService,
+ (IPowerManager)ServiceManager.getService(Context.POWER_SERVICE),
networkStats, networkManagement);
ServiceManager.addService(Context.NETWORK_POLICY_SERVICE, networkPolicy);
} catch (Throwable e) {
@@ -567,22 +676,12 @@
reportWtf("making Content Service ready", e);
}
- try {
- Slog.i(TAG, "Notification Manager");
- notification = new NotificationManagerService(context, statusBar, lights);
- ServiceManager.addService(Context.NOTIFICATION_SERVICE, notification);
- networkPolicy.bindNotificationManager(notification);
- } catch (Throwable e) {
- reportWtf("starting Notification Manager", e);
- }
+ mSystemServiceManager.startService(NotificationManagerService.class);
+ notification = INotificationManager.Stub.asInterface(
+ ServiceManager.getService(Context.NOTIFICATION_SERVICE));
+ networkPolicy.bindNotificationManager(notification);
- try {
- Slog.i(TAG, "Device Storage Monitor");
- ServiceManager.addService(DeviceStorageMonitorService.SERVICE,
- new DeviceStorageMonitorService(context));
- } catch (Throwable e) {
- reportWtf("starting DeviceStorageMonitor service", e);
- }
+ mSystemServiceManager.startService(DeviceStorageMonitorService.class);
if (!disableLocation) {
try {
@@ -624,10 +723,8 @@
R.bool.config_enableWallpaperService)) {
try {
Slog.i(TAG, "Wallpaper Service");
- if (!headless) {
- wallpaper = new WallpaperManagerService(context);
- ServiceManager.addService(Context.WALLPAPER_SERVICE, wallpaper);
- }
+ wallpaper = new WallpaperManagerService(context);
+ ServiceManager.addService(Context.WALLPAPER_SERVICE, wallpaper);
} catch (Throwable e) {
reportWtf("starting Wallpaper Service", e);
}
@@ -683,34 +780,22 @@
}
}
- try {
- Slog.i(TAG, "Twilight Service");
- twilight = new TwilightService(context);
- } catch (Throwable e) {
- reportWtf("starting TwilightService", e);
- }
+ mSystemServiceManager.startService(TwilightService.class);
+ twilight = LocalServices.getService(TwilightManager.class);
- try {
- Slog.i(TAG, "UI Mode Manager Service");
- // Listen for UI mode changes
- uiMode = new UiModeManagerService(context, twilight);
- } catch (Throwable e) {
- reportWtf("starting UiModeManagerService", e);
- }
+ mSystemServiceManager.startService(UiModeManagerService.class);
if (!disableNonCoreServices) {
try {
Slog.i(TAG, "Backup Service");
- ServiceManager.addService(Context.BACKUP_SERVICE,
- new BackupManagerService(context));
+ mSystemServiceManager.startServiceIfExists(BACKUP_MANAGER_SERVICE_CLASS);
} catch (Throwable e) {
Slog.e(TAG, "Failure starting Backup Service", e);
}
try {
Slog.i(TAG, "AppWidget Service");
- appWidget = new AppWidgetService(context);
- ServiceManager.addService(Context.APPWIDGET_SERVICE, appWidget);
+ mSystemServiceManager.startServiceIfExists(APPWIDGET_SERVICE_CLASS);
} catch (Throwable e) {
reportWtf("starting AppWidget Service", e);
}
@@ -775,7 +860,7 @@
try {
Slog.i(TAG, "Dreams Service");
// Dreams (interactive idle-time views, a/k/a screen savers)
- dreamy = new DreamManagerService(context, wmHandler);
+ dreamy = new DreamManagerService(context);
ServiceManager.addService(DreamService.DREAM_SERVICE, dreamy);
} catch (Throwable e) {
reportWtf("starting DreamManagerService", e);
@@ -801,8 +886,7 @@
try {
Slog.i(TAG, "Print Service");
- printManager = new PrintManagerService(context);
- ServiceManager.addService(Context.PRINT_SERVICE, printManager);
+ mSystemServiceManager.startServiceIfExists(PRINT_MANAGER_SERVICE_CLASS);
} catch (Throwable e) {
reportWtf("starting Print Service", e);
}
@@ -822,7 +906,7 @@
// we are in safe mode.
final boolean safeMode = wm.detectSafeMode();
if (safeMode) {
- ActivityManagerService.self().enterSafeMode();
+ mActivityManagerService.enterSafeMode();
// Post the safe mode state in the Zygote class
Zygote.systemInSafeMode = true;
// Disable the JIT for the system_server process
@@ -848,21 +932,10 @@
}
}
- if (devicePolicy != null) {
- try {
- devicePolicy.systemReady();
- } catch (Throwable e) {
- reportWtf("making Device Policy Service ready", e);
- }
- }
+ // Needed by DevicePolicyManager for initialization
+ mSystemServiceManager.startBootPhase(SystemService.PHASE_LOCK_SETTINGS_READY);
- if (notification != null) {
- try {
- notification.systemReady();
- } catch (Throwable e) {
- reportWtf("making Notification Service ready", e);
- }
- }
+ mSystemServiceManager.startBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
try {
wm.systemReady();
@@ -871,7 +944,7 @@
}
if (safeMode) {
- ActivityManagerService.self().showSafeModeOverlay();
+ mActivityManagerService.showSafeModeOverlay();
}
// Update the configuration for this context by hand, because we're going
@@ -884,7 +957,8 @@
context.getResources().updateConfiguration(config, metrics);
try {
- power.systemReady(twilight, dreamy);
+ // TODO: use boot phase
+ mPowerManagerService.systemReady(twilight, dreamy);
} catch (Throwable e) {
reportWtf("making Power Manager Service ready", e);
}
@@ -896,7 +970,8 @@
}
try {
- display.systemReady(safeMode, onlyCore);
+ // TODO: use boot phase and communicate these flags some other way
+ mDisplayManagerService.systemReady(safeMode, onlyCore);
} catch (Throwable e) {
reportWtf("making Display Manager Service ready", e);
}
@@ -911,9 +986,6 @@
final ConnectivityService connectivityF = connectivity;
final DockObserver dockF = dock;
final UsbService usbF = usb;
- final TwilightService twilightF = twilight;
- final UiModeManagerService uiModeF = uiMode;
- final AppWidgetService appWidgetF = appWidget;
final WallpaperManagerService wallpaperF = wallpaper;
final InputMethodManagerService immF = imm;
final RecognitionManagerService recognitionF = recognition;
@@ -927,7 +999,6 @@
final AssetAtlasService atlasF = atlas;
final InputManagerService inputManagerF = inputManager;
final TelephonyRegistry telephonyRegistryF = telephonyRegistry;
- final PrintManagerService printManagerF = printManager;
final MediaRouterService mediaRouterF = mediaRouter;
// We now tell the activity manager it is okay to run third party
@@ -935,17 +1006,19 @@
// where third party code can really run (but before it has actually
// started launching the initial applications), for us to complete our
// initialization.
- ActivityManagerService.self().systemReady(new Runnable() {
+ mActivityManagerService.systemReady(new Runnable() {
public void run() {
Slog.i(TAG, "Making services ready");
try {
- ActivityManagerService.self().startObservingNativeCrashes();
+ mActivityManagerService.startObservingNativeCrashes();
} catch (Throwable e) {
reportWtf("observing native crashes", e);
}
- if (!headless) {
+ try {
startSystemUi(contextF);
+ } catch (Throwable e) {
+ reportWtf("starting System UI", e);
}
try {
if (mountServiceF != null) mountServiceF.systemReady();
@@ -988,16 +1061,6 @@
reportWtf("making USB Service ready", e);
}
try {
- if (twilightF != null) twilightF.systemReady();
- } catch (Throwable e) {
- reportWtf("makin Twilight Service ready", e);
- }
- try {
- if (uiModeF != null) uiModeF.systemReady();
- } catch (Throwable e) {
- reportWtf("making UI Mode Service ready", e);
- }
- try {
if (recognitionF != null) recognitionF.systemReady();
} catch (Throwable e) {
reportWtf("making Recognition Service ready", e);
@@ -1006,13 +1069,9 @@
// It is now okay to let the various system services start their
// third party code...
+ mSystemServiceManager.startBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
try {
- if (appWidgetF != null) appWidgetF.systemRunning(safeMode);
- } catch (Throwable e) {
- reportWtf("Notifying AppWidgetService running", e);
- }
- try {
if (wallpaperF != null) wallpaperF.systemRunning();
} catch (Throwable e) {
reportWtf("Notifying WallpaperService running", e);
@@ -1072,26 +1131,14 @@
}
try {
- if (printManagerF != null) printManagerF.systemRuning();
- } catch (Throwable e) {
- reportWtf("Notifying PrintManagerService running", e);
- }
-
- try {
if (mediaRouterF != null) mediaRouterF.systemRunning();
} catch (Throwable e) {
reportWtf("Notifying MediaRouterService running", e);
}
+
+ mSystemServiceManager.startBootPhase(SystemService.PHASE_BOOT_COMPLETE);
}
});
-
- // For debug builds, log event loop stalls to dropbox for analysis.
- if (StrictMode.conditionallyEnableDebugLogging()) {
- Slog.i(TAG, "Enabled StrictMode for system server main thread.");
- }
-
- Looper.loop();
- Slog.d(TAG, "System ServerThread is exiting!");
}
static final void startSystemUi(Context context) {
@@ -1102,80 +1149,3 @@
context.startServiceAsUser(intent, UserHandle.OWNER);
}
}
-
-public class SystemServer {
- private static final String TAG = "SystemServer";
-
- public static final int FACTORY_TEST_OFF = 0;
- public static final int FACTORY_TEST_LOW_LEVEL = 1;
- public static final int FACTORY_TEST_HIGH_LEVEL = 2;
-
- static Timer timer;
- static final long SNAPSHOT_INTERVAL = 60 * 60 * 1000; // 1hr
-
- // The earliest supported time. We pick one day into 1970, to
- // give any timezone code room without going into negative time.
- private static final long EARLIEST_SUPPORTED_TIME = 86400 * 1000;
-
- /**
- * Called to initialize native system services.
- */
- private static native void nativeInit();
-
- public static void main(String[] args) {
-
- /*
- * In case the runtime switched since last boot (such as when
- * the old runtime was removed in an OTA), set the system
- * property so that it is in sync. We can't do this in
- * libnativehelper's JniInvocation::Init code where we already
- * had to fallback to a different runtime because it is
- * running as root and we need to be the system user to set
- * the property. http://b/11463182
- */
- SystemProperties.set("persist.sys.dalvik.vm.lib",
- VMRuntime.getRuntime().vmLibrary());
-
- if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
- // If a device's clock is before 1970 (before 0), a lot of
- // APIs crash dealing with negative numbers, notably
- // java.io.File#setLastModified, so instead we fake it and
- // hope that time from cell towers or NTP fixes it
- // shortly.
- Slog.w(TAG, "System clock is before 1970; setting to 1970.");
- SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
- }
-
- if (SamplingProfilerIntegration.isEnabled()) {
- SamplingProfilerIntegration.start();
- timer = new Timer();
- timer.schedule(new TimerTask() {
- @Override
- public void run() {
- SamplingProfilerIntegration.writeSnapshot("system_server", null);
- }
- }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);
- }
-
- // Mmmmmm... more memory!
- dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
-
- // The system server has to run all of the time, so it needs to be
- // as efficient as possible with its memory usage.
- VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
-
- Environment.setUserRequired(true);
-
- System.loadLibrary("android_servers");
-
- Slog.i(TAG, "Entered the Android system server!");
-
- // Initialize native services.
- nativeInit();
-
- // This used to be its own separate thread, but now it is
- // just the loop we run on the main thread.
- ServerThread thr = new ServerThread();
- thr.initAndLoop();
- }
-}
diff --git a/services/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
similarity index 100%
rename from services/java/com/android/server/TelephonyRegistry.java
rename to services/core/java/com/android/server/TelephonyRegistry.java
diff --git a/services/java/com/android/server/TextServicesManagerService.java b/services/core/java/com/android/server/TextServicesManagerService.java
similarity index 100%
rename from services/java/com/android/server/TextServicesManagerService.java
rename to services/core/java/com/android/server/TextServicesManagerService.java
diff --git a/services/java/com/android/server/TwilightCalculator.java b/services/core/java/com/android/server/TwilightCalculator.java
similarity index 100%
rename from services/java/com/android/server/TwilightCalculator.java
rename to services/core/java/com/android/server/TwilightCalculator.java
diff --git a/services/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
similarity index 76%
rename from services/java/com/android/server/UiModeManagerService.java
rename to services/core/java/com/android/server/UiModeManagerService.java
index 062be01..de912dc 100644
--- a/services/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -34,9 +34,9 @@
import android.os.BatteryManager;
import android.os.Binder;
import android.os.Handler;
+import android.os.IBinder;
import android.os.PowerManager;
import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.UserHandle;
import android.provider.Settings;
import android.service.dreams.Sandman;
@@ -47,9 +47,11 @@
import com.android.internal.R;
import com.android.internal.app.DisableCarModeActivity;
-import com.android.server.TwilightService.TwilightState;
+import com.android.server.twilight.TwilightListener;
+import com.android.server.twilight.TwilightManager;
+import com.android.server.twilight.TwilightState;
-final class UiModeManagerService extends IUiModeManager.Stub {
+final class UiModeManagerService extends SystemService {
private static final String TAG = UiModeManager.class.getSimpleName();
private static final boolean LOG = false;
@@ -57,40 +59,36 @@
private static final boolean ENABLE_LAUNCH_CAR_DOCK_APP = true;
private static final boolean ENABLE_LAUNCH_DESK_DOCK_APP = true;
- private final Context mContext;
- private final TwilightService mTwilightService;
- private final Handler mHandler = new Handler();
-
final Object mLock = new Object();
-
private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
- private int mLastBroadcastState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
- private int mNightMode = UiModeManager.MODE_NIGHT_NO;
+ private int mLastBroadcastState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
+ int mNightMode = UiModeManager.MODE_NIGHT_NO;
+
private boolean mCarModeEnabled = false;
private boolean mCharging = false;
- private final int mDefaultUiModeType;
- private final boolean mCarModeKeepsScreenOn;
- private final boolean mDeskModeKeepsScreenOn;
- private final boolean mTelevision;
-
+ private int mDefaultUiModeType;
+ private boolean mCarModeKeepsScreenOn;
+ private boolean mDeskModeKeepsScreenOn;
+ private boolean mTelevision;
private boolean mComputedNightMode;
- private int mCurUiMode = 0;
+
+ int mCurUiMode = 0;
private int mSetUiMode = 0;
-
private boolean mHoldingConfiguration = false;
+
private Configuration mConfiguration = new Configuration();
+ boolean mSystemReady;
- private boolean mSystemReady;
+ private final Handler mHandler = new Handler();
+ private TwilightManager mTwilightManager;
private NotificationManager mNotificationManager;
-
private StatusBarManager mStatusBarManager;
- private final PowerManager mPowerManager;
- private final PowerManager.WakeLock mWakeLock;
+ private PowerManager.WakeLock mWakeLock;
- static Intent buildHomeIntent(String category) {
+ private static Intent buildHomeIntent(String category) {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(category);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
@@ -142,28 +140,26 @@
}
};
- private final TwilightService.TwilightListener mTwilightListener =
- new TwilightService.TwilightListener() {
+ private final TwilightListener mTwilightListener = new TwilightListener() {
@Override
public void onTwilightStateChanged() {
updateTwilight();
}
};
- public UiModeManagerService(Context context, TwilightService twilight) {
- mContext = context;
- mTwilightService = twilight;
+ @Override
+ public void onStart() {
+ final Context context = getContext();
+ mTwilightManager = getLocalService(TwilightManager.class);
+ final PowerManager powerManager =
+ (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ mWakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, TAG);
- ServiceManager.addService(Context.UI_MODE_SERVICE, this);
-
- mContext.registerReceiver(mDockModeReceiver,
+ context.registerReceiver(mDockModeReceiver,
new IntentFilter(Intent.ACTION_DOCK_EVENT));
- mContext.registerReceiver(mBatteryReceiver,
+ context.registerReceiver(mBatteryReceiver,
new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
- mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
- mWakeLock = mPowerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, TAG);
-
mConfiguration.setToDefaults();
mDefaultUiModeType = context.getResources().getInteger(
@@ -175,101 +171,139 @@
mTelevision = context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_TELEVISION);
- mNightMode = Settings.Secure.getInt(mContext.getContentResolver(),
+ mNightMode = Settings.Secure.getInt(context.getContentResolver(),
Settings.Secure.UI_NIGHT_MODE, UiModeManager.MODE_NIGHT_AUTO);
- mTwilightService.registerListener(mTwilightListener, mHandler);
+ mTwilightManager.registerListener(mTwilightListener, mHandler);
+
+ publishBinderService(Context.UI_MODE_SERVICE, mService);
}
- @Override // Binder call
- public void disableCarMode(int flags) {
- final long ident = Binder.clearCallingIdentity();
- try {
- synchronized (mLock) {
- setCarModeLocked(false);
- if (mSystemReady) {
- updateLocked(0, flags);
+ private final IBinder mService = new IUiModeManager.Stub() {
+ @Override
+ public void enableCarMode(int flags) {
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ setCarModeLocked(true);
+ if (mSystemReady) {
+ updateLocked(flags, 0);
+ }
}
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
- } finally {
- Binder.restoreCallingIdentity(ident);
}
- }
- @Override // Binder call
- public void enableCarMode(int flags) {
- final long ident = Binder.clearCallingIdentity();
- try {
- synchronized (mLock) {
- setCarModeLocked(true);
- if (mSystemReady) {
- updateLocked(flags, 0);
+ @Override
+ public void disableCarMode(int flags) {
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ setCarModeLocked(false);
+ if (mSystemReady) {
+ updateLocked(0, flags);
+ }
}
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
- @Override // Binder call
- public int getCurrentModeType() {
- final long ident = Binder.clearCallingIdentity();
- try {
- synchronized (mLock) {
- return mCurUiMode & Configuration.UI_MODE_TYPE_MASK;
- }
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
- @Override // Binder call
- public void setNightMode(int mode) {
- switch (mode) {
- case UiModeManager.MODE_NIGHT_NO:
- case UiModeManager.MODE_NIGHT_YES:
- case UiModeManager.MODE_NIGHT_AUTO:
- break;
- default:
- throw new IllegalArgumentException("Unknown mode: " + mode);
}
- final long ident = Binder.clearCallingIdentity();
- try {
- synchronized (mLock) {
- if (isDoingNightModeLocked() && mNightMode != mode) {
- Settings.Secure.putInt(mContext.getContentResolver(),
- Settings.Secure.UI_NIGHT_MODE, mode);
- mNightMode = mode;
- updateLocked(0, 0);
+ @Override
+ public int getCurrentModeType() {
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ return mCurUiMode & Configuration.UI_MODE_TYPE_MASK;
}
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
- } finally {
- Binder.restoreCallingIdentity(ident);
}
- }
- @Override // Binder call
- public int getNightMode() {
+ @Override
+ public void setNightMode(int mode) {
+ switch (mode) {
+ case UiModeManager.MODE_NIGHT_NO:
+ case UiModeManager.MODE_NIGHT_YES:
+ case UiModeManager.MODE_NIGHT_AUTO:
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown mode: " + mode);
+ }
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ if (isDoingNightModeLocked() && mNightMode != mode) {
+ Settings.Secure.putInt(getContext().getContentResolver(),
+ Settings.Secure.UI_NIGHT_MODE, mode);
+ mNightMode = mode;
+ updateLocked(0, 0);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override
+ public int getNightMode() {
+ synchronized (mLock) {
+ return mNightMode;
+ }
+ }
+
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+ != PackageManager.PERMISSION_GRANTED) {
+
+ pw.println("Permission Denial: can't dump uimode service from from pid="
+ + Binder.getCallingPid()
+ + ", uid=" + Binder.getCallingUid());
+ return;
+ }
+
+ dumpImpl(pw);
+ }
+ };
+
+ void dumpImpl(PrintWriter pw) {
synchronized (mLock) {
- return mNightMode;
+ pw.println("Current UI Mode Service state:");
+ pw.print(" mDockState="); pw.print(mDockState);
+ pw.print(" mLastBroadcastState="); pw.println(mLastBroadcastState);
+ pw.print(" mNightMode="); pw.print(mNightMode);
+ pw.print(" mCarModeEnabled="); pw.print(mCarModeEnabled);
+ pw.print(" mComputedNightMode="); pw.println(mComputedNightMode);
+ pw.print(" mCurUiMode=0x"); pw.print(Integer.toHexString(mCurUiMode));
+ pw.print(" mSetUiMode=0x"); pw.println(Integer.toHexString(mSetUiMode));
+ pw.print(" mHoldingConfiguration="); pw.print(mHoldingConfiguration);
+ pw.print(" mSystemReady="); pw.println(mSystemReady);
+ pw.print(" mTwilightService.getCurrentState()=");
+ pw.println(mTwilightManager.getCurrentState());
}
}
- void systemReady() {
- synchronized (mLock) {
- mSystemReady = true;
- mCarModeEnabled = mDockState == Intent.EXTRA_DOCK_STATE_CAR;
- updateComputedNightModeLocked();
- updateLocked(0, 0);
+ @Override
+ public void onBootPhase(int phase) {
+ if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
+ synchronized (mLock) {
+ mSystemReady = true;
+ mCarModeEnabled = mDockState == Intent.EXTRA_DOCK_STATE_CAR;
+ updateComputedNightModeLocked();
+ updateLocked(0, 0);
+ }
}
}
- private boolean isDoingNightModeLocked() {
+ boolean isDoingNightModeLocked() {
return mCarModeEnabled || mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED;
}
- private void setCarModeLocked(boolean enabled) {
+ void setCarModeLocked(boolean enabled) {
if (mCarModeEnabled != enabled) {
mCarModeEnabled = enabled;
}
@@ -344,7 +378,7 @@
}
}
- private void updateLocked(int enableFlags, int disableFlags) {
+ void updateLocked(int enableFlags, int disableFlags) {
String action = null;
String oldAction = null;
if (mLastBroadcastState == Intent.EXTRA_DOCK_STATE_CAR) {
@@ -359,7 +393,7 @@
adjustStatusBarCarModeLocked();
if (oldAction != null) {
- mContext.sendBroadcastAsUser(new Intent(oldAction), UserHandle.ALL);
+ getContext().sendBroadcastAsUser(new Intent(oldAction), UserHandle.ALL);
}
mLastBroadcastState = Intent.EXTRA_DOCK_STATE_CAR;
action = UiModeManager.ACTION_ENTER_CAR_MODE;
@@ -367,7 +401,7 @@
} else if (isDeskDockState(mDockState)) {
if (!isDeskDockState(mLastBroadcastState)) {
if (oldAction != null) {
- mContext.sendBroadcastAsUser(new Intent(oldAction), UserHandle.ALL);
+ getContext().sendBroadcastAsUser(new Intent(oldAction), UserHandle.ALL);
}
mLastBroadcastState = mDockState;
action = UiModeManager.ACTION_ENTER_DESK_MODE;
@@ -393,7 +427,7 @@
Intent intent = new Intent(action);
intent.putExtra("enableFlags", enableFlags);
intent.putExtra("disableFlags", disableFlags);
- mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, null,
+ getContext().sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, null,
mResultReceiver, null, Activity.RESULT_OK, null, null);
// Attempting to make this transition a little more clean, we are going
@@ -491,7 +525,7 @@
// activity manager take care of both the start and config
// change.
Intent homeIntent = buildHomeIntent(category);
- if (Sandman.shouldStartDockApp(mContext, homeIntent)) {
+ if (Sandman.shouldStartDockApp(getContext(), homeIntent)) {
try {
int result = ActivityManagerNative.getDefault().startActivityWithConfig(
null, null, homeIntent, null, null, null, 0, 0,
@@ -513,14 +547,15 @@
// If we did not start a dock app, then start dreaming if supported.
if (category != null && !dockAppStarted) {
- Sandman.startDreamWhenDockedIfAppropriate(mContext);
+ Sandman.startDreamWhenDockedIfAppropriate(getContext());
}
}
private void adjustStatusBarCarModeLocked() {
+ final Context context = getContext();
if (mStatusBarManager == null) {
mStatusBarManager = (StatusBarManager)
- mContext.getSystemService(Context.STATUS_BAR_SERVICE);
+ context.getSystemService(Context.STATUS_BAR_SERVICE);
}
// Fear not: StatusBarManagerService manages a list of requests to disable
@@ -536,12 +571,12 @@
if (mNotificationManager == null) {
mNotificationManager = (NotificationManager)
- mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+ context.getSystemService(Context.NOTIFICATION_SERVICE);
}
if (mNotificationManager != null) {
if (mCarModeEnabled) {
- Intent carModeOffIntent = new Intent(mContext, DisableCarModeActivity.class);
+ Intent carModeOffIntent = new Intent(context, DisableCarModeActivity.class);
Notification n = new Notification();
n.icon = R.drawable.stat_notify_car_mode;
@@ -549,10 +584,10 @@
n.flags = Notification.FLAG_ONGOING_EVENT;
n.when = 0;
n.setLatestEventInfo(
- mContext,
- mContext.getString(R.string.car_mode_disable_notification_title),
- mContext.getString(R.string.car_mode_disable_notification_message),
- PendingIntent.getActivityAsUser(mContext, 0, carModeOffIntent, 0,
+ context,
+ context.getString(R.string.car_mode_disable_notification_title),
+ context.getString(R.string.car_mode_disable_notification_message),
+ PendingIntent.getActivityAsUser(context, 0, carModeOffIntent, 0,
null, UserHandle.CURRENT));
mNotificationManager.notifyAsUser(null,
R.string.car_mode_disable_notification_title, n, UserHandle.ALL);
@@ -563,7 +598,7 @@
}
}
- private void updateTwilight() {
+ void updateTwilight() {
synchronized (mLock) {
if (isDoingNightModeLocked() && mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
updateComputedNightModeLocked();
@@ -573,36 +608,11 @@
}
private void updateComputedNightModeLocked() {
- TwilightState state = mTwilightService.getCurrentState();
+ TwilightState state = mTwilightManager.getCurrentState();
if (state != null) {
mComputedNightMode = state.isNight();
}
}
- @Override
- protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump uimode service from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
-
- synchronized (mLock) {
- pw.println("Current UI Mode Service state:");
- pw.print(" mDockState="); pw.print(mDockState);
- pw.print(" mLastBroadcastState="); pw.println(mLastBroadcastState);
- pw.print(" mNightMode="); pw.print(mNightMode);
- pw.print(" mCarModeEnabled="); pw.print(mCarModeEnabled);
- pw.print(" mComputedNightMode="); pw.println(mComputedNightMode);
- pw.print(" mCurUiMode=0x"); pw.print(Integer.toHexString(mCurUiMode));
- pw.print(" mSetUiMode=0x"); pw.println(Integer.toHexString(mSetUiMode));
- pw.print(" mHoldingConfiguration="); pw.print(mHoldingConfiguration);
- pw.print(" mSystemReady="); pw.println(mSystemReady);
- pw.print(" mTwilightService.getCurrentState()=");
- pw.println(mTwilightService.getCurrentState());
- }
- }
}
diff --git a/services/java/com/android/server/UiThread.java b/services/core/java/com/android/server/UiThread.java
similarity index 66%
rename from services/java/com/android/server/UiThread.java
rename to services/core/java/com/android/server/UiThread.java
index 60d73aa..0beb77f 100644
--- a/services/java/com/android/server/UiThread.java
+++ b/services/core/java/com/android/server/UiThread.java
@@ -17,21 +17,18 @@
package com.android.server;
import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.StrictMode;
-import android.util.Slog;
/**
* Shared singleton thread for showing UI. This is a foreground thread, and in
* additional should not have operations that can take more than a few ms scheduled
* on it to avoid UI jank.
*/
-public final class UiThread extends HandlerThread {
+public final class UiThread extends ServiceThread {
private static UiThread sInstance;
private static Handler sHandler;
private UiThread() {
- super("android.ui", android.os.Process.THREAD_PRIORITY_FOREGROUND);
+ super("android.ui", android.os.Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
}
private static void ensureThreadLocked() {
@@ -39,19 +36,6 @@
sInstance = new UiThread();
sInstance.start();
sHandler = new Handler(sInstance.getLooper());
- sHandler.post(new Runnable() {
- @Override
- public void run() {
- //Looper.myLooper().setMessageLogging(new LogPrinter(
- // Log.VERBOSE, "WindowManagerPolicy", Log.LOG_ID_SYSTEM));
- android.os.Process.setCanSelfBackground(false);
-
- // For debug builds, log event loop stalls to dropbox for analysis.
- if (StrictMode.conditionallyEnableDebugLogging()) {
- Slog.i("UiThread", "Enabled StrictMode logging for UI thread");
- }
- }
- });
}
}
diff --git a/services/java/com/android/server/UpdateLockService.java b/services/core/java/com/android/server/UpdateLockService.java
similarity index 100%
rename from services/java/com/android/server/UpdateLockService.java
rename to services/core/java/com/android/server/UpdateLockService.java
diff --git a/services/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
similarity index 100%
rename from services/java/com/android/server/VibratorService.java
rename to services/core/java/com/android/server/VibratorService.java
diff --git a/services/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
similarity index 95%
rename from services/java/com/android/server/Watchdog.java
rename to services/core/java/com/android/server/Watchdog.java
index e17f42d..1ce073a 100644
--- a/services/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -20,18 +20,15 @@
import android.os.Binder;
import android.os.RemoteException;
import com.android.server.am.ActivityManagerService;
-import com.android.server.power.PowerManagerService;
-import android.app.AlarmManager;
-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.os.BatteryManager;
import android.os.Debug;
import android.os.Handler;
+import android.os.IPowerManager;
import android.os.Looper;
import android.os.Process;
import android.os.ServiceManager;
@@ -45,7 +42,6 @@
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.Calendar;
/** This class calls its monitor every minute. Killing this process if they don't return **/
public class Watchdog extends Thread {
@@ -80,9 +76,6 @@
final ArrayList<HandlerChecker> mHandlerCheckers = new ArrayList<HandlerChecker>();
final HandlerChecker mMonitorChecker;
ContentResolver mResolver;
- BatteryService mBattery;
- PowerManagerService mPower;
- AlarmManagerService mAlarm;
ActivityManagerService mActivity;
int mPhonePid;
@@ -232,15 +225,13 @@
// And also check IO thread.
mHandlerCheckers.add(new HandlerChecker(IoThread.getHandler(),
"i/o thread", DEFAULT_TIMEOUT));
+ // And the display thread.
+ mHandlerCheckers.add(new HandlerChecker(DisplayThread.getHandler(),
+ "display thread", DEFAULT_TIMEOUT));
}
- public void init(Context context, BatteryService battery,
- PowerManagerService power, AlarmManagerService alarm,
- ActivityManagerService activity) {
+ public void init(Context context, ActivityManagerService activity) {
mResolver = context.getContentResolver();
- mBattery = battery;
- mPower = power;
- mAlarm = alarm;
mActivity = activity;
context.registerReceiver(new RebootRequestReceiver(),
@@ -277,15 +268,16 @@
}
}
- public void addThread(Handler thread, String name) {
- addThread(thread, name, DEFAULT_TIMEOUT);
+ public void addThread(Handler thread) {
+ addThread(thread, DEFAULT_TIMEOUT);
}
- public void addThread(Handler thread, String name, long timeoutMillis) {
+ public void addThread(Handler thread, long timeoutMillis) {
synchronized (this) {
if (isAlive()) {
throw new RuntimeException("Threads can't be added once the Watchdog is running");
}
+ final String name = thread.getLooper().getThread().getName();
mHandlerCheckers.add(new HandlerChecker(thread, name, timeoutMillis));
}
}
@@ -295,8 +287,11 @@
*/
void rebootSystem(String reason) {
Slog.i(TAG, "Rebooting system because: " + reason);
- PowerManagerService pms = (PowerManagerService) ServiceManager.getService("power");
- pms.reboot(false, reason, false);
+ IPowerManager pms = (IPowerManager)ServiceManager.getService(Context.POWER_SERVICE);
+ try {
+ pms.reboot(false, reason, false);
+ } catch (RemoteException ex) {
+ }
}
private int evaluateCheckerCompletionLocked() {
diff --git a/services/java/com/android/server/WiredAccessoryManager.java b/services/core/java/com/android/server/WiredAccessoryManager.java
similarity index 100%
rename from services/java/com/android/server/WiredAccessoryManager.java
rename to services/core/java/com/android/server/WiredAccessoryManager.java
diff --git a/services/java/com/android/server/accounts/AccountAuthenticatorCache.java b/services/core/java/com/android/server/accounts/AccountAuthenticatorCache.java
similarity index 100%
rename from services/java/com/android/server/accounts/AccountAuthenticatorCache.java
rename to services/core/java/com/android/server/accounts/AccountAuthenticatorCache.java
diff --git a/services/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
similarity index 100%
rename from services/java/com/android/server/accounts/AccountManagerService.java
rename to services/core/java/com/android/server/accounts/AccountManagerService.java
diff --git a/services/java/com/android/server/accounts/IAccountAuthenticatorCache.java b/services/core/java/com/android/server/accounts/IAccountAuthenticatorCache.java
similarity index 100%
rename from services/java/com/android/server/accounts/IAccountAuthenticatorCache.java
rename to services/core/java/com/android/server/accounts/IAccountAuthenticatorCache.java
diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
similarity index 100%
rename from services/java/com/android/server/am/ActiveServices.java
rename to services/core/java/com/android/server/am/ActiveServices.java
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
similarity index 98%
rename from services/java/com/android/server/am/ActivityManagerService.java
rename to services/core/java/com/android/server/am/ActivityManagerService.java
index 264a809..9ea242c 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -28,11 +28,15 @@
import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
import android.app.AppOpsManager;
+import android.app.IActivityContainer;
+import android.app.IActivityContainerCallback;
import android.appwidget.AppWidgetManager;
+import android.graphics.Rect;
import android.util.ArrayMap;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IAppOpsService;
+import com.android.internal.app.ProcessMap;
import com.android.internal.app.ProcessStats;
import com.android.internal.os.BackgroundThread;
import com.android.internal.os.BatteryStatsImpl;
@@ -45,14 +49,14 @@
import com.android.server.AppOpsService;
import com.android.server.AttributeCache;
import com.android.server.IntentResolver;
-import com.android.internal.app.ProcessMap;
+import com.android.server.ServiceThread;
import com.android.server.SystemServer;
+import com.android.server.SystemService;
import com.android.server.Watchdog;
import com.android.server.am.ActivityStack.ActivityState;
import com.android.server.firewall.IntentFirewall;
import com.android.server.pm.UserManagerService;
import com.android.server.wm.AppTransition;
-import com.android.server.wm.StackBox;
import com.android.server.wm.WindowManagerService;
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
@@ -68,7 +72,6 @@
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
-import android.app.ActivityManager.StackBoxInfo;
import android.app.ActivityManager.StackInfo;
import android.app.ActivityManagerNative;
import android.app.ActivityOptions;
@@ -134,6 +137,7 @@
import android.os.Debug;
import android.os.DropBoxManager;
import android.os.Environment;
+import android.os.FactoryTest;
import android.os.FileObserver;
import android.os.FileUtils;
import android.os.Handler;
@@ -331,8 +335,6 @@
public IntentFirewall mIntentFirewall;
- private final boolean mHeadless;
-
// Whether we should show our dialogs (ANR, crash, etc) or just perform their
// default actuion automatically. Important for devices without direct input
// devices.
@@ -747,7 +749,7 @@
}
}
- private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
+ private static final ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
/**
* All information we have collected about the runtime performance of
@@ -996,8 +998,7 @@
WindowManagerService mWindowManager;
- static ActivityManagerService mSelf;
- static ActivityThread mSystemThread;
+ final ActivityThread mSystemThread;
int mCurrentUserId = 0;
private UserManagerService mUserManager;
@@ -1074,10 +1075,13 @@
*/
private boolean mUserIsMonkey;
- final Handler mHandler = new Handler() {
- //public Handler() {
- // if (localLOGV) Slog.v(TAG, "Handler started!");
- //}
+ final ServiceThread mHandlerThread;
+ final MainHandler mHandler;
+
+ final class MainHandler extends Handler {
+ public MainHandler(Looper looper) {
+ super(looper, null, true);
+ }
@Override
public void handleMessage(Message msg) {
@@ -1730,38 +1734,34 @@
}
};
- public static void setSystemProcess() {
+ public void setSystemProcess() {
try {
- ActivityManagerService m = mSelf;
-
- ServiceManager.addService(Context.ACTIVITY_SERVICE, m, true);
- ServiceManager.addService(ProcessStats.SERVICE_NAME, m.mProcessStats);
- ServiceManager.addService("meminfo", new MemBinder(m));
- ServiceManager.addService("gfxinfo", new GraphicsBinder(m));
- ServiceManager.addService("dbinfo", new DbBinder(m));
+ ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
+ ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
+ ServiceManager.addService("meminfo", new MemBinder(this));
+ ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
+ ServiceManager.addService("dbinfo", new DbBinder(this));
if (MONITOR_CPU_USAGE) {
- ServiceManager.addService("cpuinfo", new CpuBinder(m));
+ ServiceManager.addService("cpuinfo", new CpuBinder(this));
}
- ServiceManager.addService("permission", new PermissionController(m));
+ ServiceManager.addService("permission", new PermissionController(this));
- ApplicationInfo info =
- mSelf.mContext.getPackageManager().getApplicationInfo(
- "android", STOCK_PM_FLAGS);
+ ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(
+ "android", STOCK_PM_FLAGS);
mSystemThread.installSystemApplicationInfo(info);
- synchronized (mSelf) {
- ProcessRecord app = mSelf.newProcessRecordLocked(info,
- info.processName, false);
+ synchronized (this) {
+ ProcessRecord app = newProcessRecordLocked(info, info.processName, false);
app.persistent = true;
app.pid = MY_PID;
app.maxAdj = ProcessList.SYSTEM_ADJ;
- app.makeActive(mSystemThread.getApplicationThread(), mSelf.mProcessStats);
- mSelf.mProcessNames.put(app.processName, app.uid, app);
- synchronized (mSelf.mPidsSelfLocked) {
- mSelf.mPidsSelfLocked.put(app.pid, app);
+ app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
+ mProcessNames.put(app.processName, app.uid, app);
+ synchronized (mPidsSelfLocked) {
+ mPidsSelfLocked.put(app.pid, app);
}
- mSelf.updateLruProcessLocked(app, false, null);
- mSelf.updateOomAdjLocked();
+ updateLruProcessLocked(app, false, null);
+ updateOomAdjLocked();
}
} catch (PackageManager.NameNotFoundException e) {
throw new RuntimeException(
@@ -1772,105 +1772,17 @@
public void setWindowManager(WindowManagerService wm) {
mWindowManager = wm;
mStackSupervisor.setWindowManager(wm);
- wm.createStack(HOME_STACK_ID, -1, StackBox.TASK_STACK_GOES_OVER, 1.0f);
}
public void startObservingNativeCrashes() {
- final NativeCrashListener ncl = new NativeCrashListener();
+ final NativeCrashListener ncl = new NativeCrashListener(this);
ncl.start();
}
- public static final Context main(int factoryTest) {
- AThread thr = new AThread();
- thr.start();
-
- synchronized (thr) {
- while (thr.mService == null) {
- try {
- thr.wait();
- } catch (InterruptedException e) {
- }
- }
- }
-
- ActivityManagerService m = thr.mService;
- mSelf = m;
- ActivityThread at = ActivityThread.systemMain();
- mSystemThread = at;
- Context context = at.getSystemContext();
- context.setTheme(android.R.style.Theme_Holo);
- m.mContext = context;
- m.mFactoryTest = factoryTest;
- m.mIntentFirewall = new IntentFirewall(m.new IntentFirewallInterface());
-
- m.mStackSupervisor = new ActivityStackSupervisor(m, context, thr.mLooper);
-
- m.mBatteryStatsService.publish(context);
- m.mUsageStatsService.publish(context);
- m.mAppOpsService.publish(context);
-
- synchronized (thr) {
- thr.mReady = true;
- thr.notifyAll();
- }
-
- m.startRunning(null, null, null, null);
-
- return context;
- }
-
- public static ActivityManagerService self() {
- return mSelf;
- }
-
public IAppOpsService getAppOpsService() {
return mAppOpsService;
}
- static class AThread extends Thread {
- ActivityManagerService mService;
- Looper mLooper;
- boolean mReady = false;
-
- public AThread() {
- super("ActivityManager");
- }
-
- @Override
- public void run() {
- Looper.prepare();
-
- android.os.Process.setThreadPriority(
- android.os.Process.THREAD_PRIORITY_FOREGROUND);
- android.os.Process.setCanSelfBackground(false);
-
- ActivityManagerService m = new ActivityManagerService();
-
- synchronized (this) {
- mService = m;
- mLooper = Looper.myLooper();
- Watchdog.getInstance().addThread(new Handler(mLooper), getName());
- notifyAll();
- }
-
- synchronized (this) {
- while (!mReady) {
- try {
- wait();
- } catch (InterruptedException e) {
- }
- }
- }
-
- // For debug builds, log event loop stalls to dropbox for analysis.
- if (StrictMode.conditionallyEnableDebugLogging()) {
- Slog.i(TAG, "Enabled StrictMode logging for AThread's Looper");
- }
-
- Looper.loop();
- }
- }
-
static class MemBinder extends Binder {
ActivityManagerService mActivityManagerService;
MemBinder(ActivityManagerService activityManagerService) {
@@ -1955,22 +1867,54 @@
}
}
- private ActivityManagerService() {
+ public static class Lifecycle extends SystemService {
+ private ActivityManagerService mService;
+
+ @Override
+ public void onCreate(Context context) {
+ mService = new ActivityManagerService(context);
+ }
+
+ @Override
+ public void onStart() {
+ mService.start();
+ }
+
+ public ActivityManagerService getService() {
+ return mService;
+ }
+ }
+
+ // Note: This method is invoked on the main thread but may need to attach various
+ // handlers to other threads. So take care to be explicit about the looper.
+ public ActivityManagerService(Context systemContext) {
+ mContext = systemContext;
+ mFactoryTest = FactoryTest.getMode();
+ mSystemThread = ActivityThread.currentActivityThread();
+
Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
- mFgBroadcastQueue = new BroadcastQueue(this, "foreground", BROADCAST_FG_TIMEOUT, false);
- mBgBroadcastQueue = new BroadcastQueue(this, "background", BROADCAST_BG_TIMEOUT, true);
+ mHandlerThread = new ServiceThread(TAG,
+ android.os.Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
+ mHandlerThread.start();
+ mHandler = new MainHandler(mHandlerThread.getLooper());
+
+ mFgBroadcastQueue = new BroadcastQueue(this, mHandler,
+ "foreground", BROADCAST_FG_TIMEOUT, false);
+ mBgBroadcastQueue = new BroadcastQueue(this, mHandler,
+ "background", BROADCAST_BG_TIMEOUT, true);
mBroadcastQueues[0] = mFgBroadcastQueue;
mBroadcastQueues[1] = mBgBroadcastQueue;
mServices = new ActiveServices(this);
mProviderMap = new ProviderMap(this);
+ // TODO: Move creation of battery stats service outside of activity manager service.
File dataDir = Environment.getDataDirectory();
File systemDir = new File(dataDir, "system");
systemDir.mkdirs();
mBatteryStatsService = new BatteryStatsService(new File(
- systemDir, "batterystats.bin").toString());
+ systemDir, "batterystats.bin").toString(), mHandler);
mBatteryStatsService.getActiveStatistics().readLocked();
mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
mOnBattery = DEBUG_POWER ? true
@@ -1980,12 +1924,10 @@
mProcessStats = new ProcessStatsService(this, new File(systemDir, "procstats"));
mUsageStatsService = new UsageStatsService(new File(systemDir, "usagestats").toString());
- mAppOpsService = new AppOpsService(new File(systemDir, "appops.xml"));
+ mAppOpsService = new AppOpsService(new File(systemDir, "appops.xml"), mHandler);
mGrantFile = new AtomicFile(new File(systemDir, "urigrants.xml"));
- mHeadless = "1".equals(SystemProperties.get("ro.config.headless", "0"));
-
// User 0 is the first and only user that runs at boot.
mStartedUsers.put(0, new UserStartedState(new UserHandle(0), true));
mUserLru.add(Integer.valueOf(0));
@@ -2000,10 +1942,9 @@
mConfigurationSeq = mConfiguration.seq = 1;
mProcessCpuTracker.init();
- mCompatModePackages = new CompatModePackages(this, systemDir);
-
- // Add ourself to the Watchdog monitors.
- Watchdog.getInstance().addMonitor(this);
+ mCompatModePackages = new CompatModePackages(this, systemDir, mHandler);
+ mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(), mHandler);
+ mStackSupervisor = new ActivityStackSupervisor(this);
mProcessCpuThread = new Thread("CpuTracker") {
@Override
@@ -2034,7 +1975,18 @@
}
}
};
+
+ Watchdog.getInstance().addMonitor(this);
+ Watchdog.getInstance().addThread(mHandler);
+ }
+
+ private void start() {
mProcessCpuThread.start();
+
+ mBatteryStatsService.publish(mContext);
+ mUsageStatsService.publish(mContext);
+ mAppOpsService.publish(mContext);
+ startRunning(null, null, null, null);
}
@Override
@@ -2730,13 +2682,13 @@
}
gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
}
- if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
- if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
+ if (mFactoryTest != FactoryTest.FACTORY_TEST_OFF) {
+ if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
&& mTopComponent != null
&& app.processName.equals(mTopComponent.getPackageName())) {
uid = 0;
}
- if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
+ if (mFactoryTest == FactoryTest.FACTORY_TEST_HIGH_LEVEL
&& (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
uid = 0;
}
@@ -2846,21 +2798,14 @@
Intent getHomeIntent() {
Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
intent.setComponent(mTopComponent);
- if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
+ if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
intent.addCategory(Intent.CATEGORY_HOME);
}
return intent;
}
boolean startHomeActivityLocked(int userId) {
- if (mHeadless) {
- // Added because none of the other calls to ensureBootCompleted seem to fire
- // when running headless.
- ensureBootCompleted();
- return false;
- }
-
- if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
+ if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
&& mTopAction == null) {
// We are running in factory test mode, but unable to find
// the factory test app, so just sit around displaying the
@@ -2924,14 +2869,14 @@
// version than the last one shown, and we are not running in
// low-level factory test mode.
final ContentResolver resolver = mContext.getContentResolver();
- if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
+ if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL &&
Settings.Global.getInt(resolver,
Settings.Global.DEVICE_PROVISIONED, 0) != 0) {
mCheckedForSetup = true;
// See if we should be showing the platform update setup UI.
Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
- List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
+ List<ResolveInfo> ris = mContext.getPackageManager()
.queryIntentActivities(intent, PackageManager.GET_META_DATA);
// We don't allow third party apps to replace this.
@@ -2959,7 +2904,7 @@
intent.setComponent(new ComponentName(
ri.activityInfo.packageName, ri.activityInfo.name));
mStackSupervisor.startActivityLocked(null, intent, null, ri.activityInfo,
- null, null, 0, 0, 0, null, 0, null, false, null);
+ null, null, 0, 0, 0, null, 0, null, false, null, null);
}
}
}
@@ -3117,7 +3062,7 @@
// TODO: Switch to user app stacks here.
return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profileFile, profileFd,
- null, null, options, userId);
+ null, null, options, userId, null);
}
@Override
@@ -3132,7 +3077,7 @@
// TODO: Switch to user app stacks here.
mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profileFile, profileFd,
- res, null, options, UserHandle.getCallingUserId());
+ res, null, options, UserHandle.getCallingUserId(), null);
return res;
}
@@ -3147,7 +3092,7 @@
// TODO: Switch to user app stacks here.
int ret = mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, resultTo, resultWho, requestCode, startFlags,
- null, null, null, config, options, userId);
+ null, null, null, config, options, userId, null);
return ret;
}
@@ -3278,7 +3223,7 @@
int res = mStackSupervisor.startActivityLocked(r.app.thread, intent,
r.resolvedType, aInfo, resultTo != null ? resultTo.appToken : null,
resultWho, requestCode, -1, r.launchedFromUid, r.launchedFromPackage, 0,
- options, false, null);
+ options, false, null, null);
Binder.restoreCallingIdentity(origId);
r.finishing = wasFinishing;
@@ -3299,7 +3244,7 @@
// TODO: Switch to user app stacks here.
int ret = mStackSupervisor.startActivityMayWait(null, uid, callingPackage, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags,
- null, null, null, null, options, userId);
+ null, null, null, null, options, userId, null);
return ret;
}
@@ -5004,7 +4949,7 @@
// See if the top visible activity is waiting to run in this process...
if (normalMode) {
try {
- if (mStackSupervisor.attachApplicationLocked(app, mHeadless)) {
+ if (mStackSupervisor.attachApplicationLocked(app)) {
didSomething = true;
}
} catch (Exception e) {
@@ -5161,7 +5106,7 @@
}
}
- if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
+ if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
// Start looking for apps that are abusing wake locks.
Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
@@ -7111,23 +7056,40 @@
}
@Override
- public int createStack(int taskId, int relativeStackBoxId, int position, float weight) {
+ public IBinder getHomeActivityToken() throws RemoteException {
enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
- "createStack()");
- if (DEBUG_STACK) Slog.d(TAG, "createStack: taskId=" + taskId + " relStackBoxId=" +
- relativeStackBoxId + " position=" + position + " weight=" + weight);
+ "getHomeActivityToken()");
synchronized (this) {
- long ident = Binder.clearCallingIdentity();
- try {
- int stackId = mStackSupervisor.createStack();
- mWindowManager.createStack(stackId, relativeStackBoxId, position, weight);
- if (taskId > 0) {
- moveTaskToStack(taskId, stackId, true);
- }
- return stackId;
- } finally {
- Binder.restoreCallingIdentity(ident);
+ return mStackSupervisor.getHomeActivityToken();
+ }
+ }
+
+ @Override
+ public IActivityContainer createActivityContainer(IBinder parentActivityToken,
+ IActivityContainerCallback callback) throws RemoteException {
+ enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
+ "createActivityContainer()");
+ synchronized (this) {
+ if (parentActivityToken == null) {
+ throw new IllegalArgumentException("parent token must not be null");
}
+ ActivityRecord r = ActivityRecord.forToken(parentActivityToken);
+ if (r == null) {
+ return null;
+ }
+ return mStackSupervisor.createActivityContainer(r, callback);
+ }
+ }
+
+ @Override
+ public IActivityContainer getEnclosingActivityContainer(IBinder activityToken)
+ throws RemoteException {
+ synchronized (this) {
+ ActivityStack stack = ActivityRecord.getStackLocked(activityToken);
+ if (stack != null) {
+ return stack.mActivityContainer;
+ }
+ return null;
}
}
@@ -7152,99 +7114,40 @@
}
@Override
- public void resizeStackBox(int stackBoxId, float weight) {
+ public void resizeStack(int stackBoxId, Rect bounds) {
enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
"resizeStackBox()");
long ident = Binder.clearCallingIdentity();
try {
- mWindowManager.resizeStackBox(stackBoxId, weight);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
- private ArrayList<StackInfo> getStacks() {
- synchronized (this) {
- ArrayList<ActivityManager.StackInfo> list = new ArrayList<ActivityManager.StackInfo>();
- ArrayList<ActivityStack> stacks = mStackSupervisor.getStacks();
- for (ActivityStack stack : stacks) {
- ActivityManager.StackInfo stackInfo = new ActivityManager.StackInfo();
- int stackId = stack.mStackId;
- stackInfo.stackId = stackId;
- stackInfo.bounds = mWindowManager.getStackBounds(stackId);
- ArrayList<TaskRecord> tasks = stack.getAllTasks();
- final int numTasks = tasks.size();
- int[] taskIds = new int[numTasks];
- String[] taskNames = new String[numTasks];
- for (int i = 0; i < numTasks; ++i) {
- final TaskRecord task = tasks.get(i);
- taskIds[i] = task.taskId;
- taskNames[i] = task.origActivity != null ? task.origActivity.flattenToString()
- : task.realActivity != null ? task.realActivity.flattenToString()
- : task.getTopActivity() != null ? task.getTopActivity().packageName
- : "unknown";
- }
- stackInfo.taskIds = taskIds;
- stackInfo.taskNames = taskNames;
- list.add(stackInfo);
- }
- return list;
- }
- }
-
- private void addStackInfoToStackBoxInfo(StackBoxInfo stackBoxInfo, List<StackInfo> stackInfos) {
- final int stackId = stackBoxInfo.stackId;
- if (stackId >= 0) {
- for (StackInfo stackInfo : stackInfos) {
- if (stackId == stackInfo.stackId) {
- stackBoxInfo.stack = stackInfo;
- stackInfos.remove(stackInfo);
- return;
- }
- }
- } else {
- addStackInfoToStackBoxInfo(stackBoxInfo.children[0], stackInfos);
- addStackInfoToStackBoxInfo(stackBoxInfo.children[1], stackInfos);
- }
- }
-
- @Override
- public List<StackBoxInfo> getStackBoxes() {
- enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
- "getStackBoxes()");
- long ident = Binder.clearCallingIdentity();
- try {
- List<StackBoxInfo> stackBoxInfos = mWindowManager.getStackBoxInfos();
- synchronized (this) {
- List<StackInfo> stackInfos = getStacks();
- for (StackBoxInfo stackBoxInfo : stackBoxInfos) {
- addStackInfoToStackBoxInfo(stackBoxInfo, stackInfos);
- }
- }
- return stackBoxInfos;
+ mWindowManager.resizeStack(stackBoxId, bounds);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override
- public StackBoxInfo getStackBoxInfo(int stackBoxId) {
+ public List<StackInfo> getAllStackInfos() {
enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
- "getStackBoxInfo()");
+ "getAllStackInfos()");
long ident = Binder.clearCallingIdentity();
try {
- List<StackBoxInfo> stackBoxInfos = mWindowManager.getStackBoxInfos();
- StackBoxInfo info = null;
synchronized (this) {
- List<StackInfo> stackInfos = getStacks();
- for (StackBoxInfo stackBoxInfo : stackBoxInfos) {
- addStackInfoToStackBoxInfo(stackBoxInfo, stackInfos);
- if (stackBoxInfo.stackBoxId == stackBoxId) {
- info = stackBoxInfo;
- }
- }
+ return mStackSupervisor.getAllStackInfosLocked();
}
- return info;
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override
+ public StackInfo getStackInfo(int stackId) {
+ enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
+ "getStackInfo()");
+ long ident = Binder.clearCallingIdentity();
+ try {
+ synchronized (this) {
+ return mStackSupervisor.getStackInfoLocked(stackId);
+ }
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -8065,11 +7968,11 @@
}
}
- public static final void installSystemProviders() {
+ public final void installSystemProviders() {
List<ProviderInfo> providers;
- synchronized (mSelf) {
- ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
- providers = mSelf.generateApplicationProvidersLocked(app);
+ synchronized (this) {
+ ProcessRecord app = mProcessNames.get("system", Process.SYSTEM_UID);
+ providers = generateApplicationProvidersLocked(app);
if (providers != null) {
for (int i=providers.size()-1; i>=0; i--) {
ProviderInfo pi = (ProviderInfo)providers.get(i);
@@ -8085,9 +7988,9 @@
mSystemThread.installSystemProviders(providers);
}
- mSelf.mCoreSettingsObserver = new CoreSettingsObserver(mSelf);
+ mCoreSettingsObserver = new CoreSettingsObserver(this);
- mSelf.mUsageStatsService.monitorPackages();
+ mUsageStatsService.monitorPackages();
}
/**
@@ -9325,7 +9228,7 @@
synchronized(this) {
// Make sure we have no pre-ready processes sitting around.
- if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
+ if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL) {
ResolveInfo ri = mContext.getPackageManager()
.resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
STOCK_PM_FLAGS);
@@ -9367,7 +9270,7 @@
if (goingCallback != null) goingCallback.run();
synchronized (this) {
- if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
+ if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
try {
List apps = AppGlobals.getPackageManager().
getPersistentApplications(STOCK_PM_FLAGS);
@@ -9500,10 +9403,6 @@
private boolean handleAppCrashLocked(ProcessRecord app, String shortMsg, String longMsg,
String stackTrace) {
- if (mHeadless) {
- Log.e(TAG, "handleAppCrashLocked: " + app.processName);
- return false;
- }
long now = SystemClock.uptimeMillis();
Long crashTime;
@@ -14047,9 +13946,6 @@
*/
boolean updateConfigurationLocked(Configuration values,
ActivityRecord starting, boolean persistent, boolean initLocale) {
- // do nothing if we are headless
- if (mHeadless) return true;
-
int changes = 0;
if (values != null) {
@@ -14132,18 +14028,21 @@
boolean kept = true;
final ActivityStack mainStack = mStackSupervisor.getFocusedStack();
- if (changes != 0 && starting == null) {
- // If the configuration changed, and the caller is not already
- // in the process of starting an activity, then find the top
- // activity to check if its configuration needs to change.
- starting = mainStack.topRunningActivityLocked(null);
- }
+ // mainStack is null during startup.
+ if (mainStack != null) {
+ if (changes != 0 && starting == null) {
+ // If the configuration changed, and the caller is not already
+ // in the process of starting an activity, then find the top
+ // activity to check if its configuration needs to change.
+ starting = mainStack.topRunningActivityLocked(null);
+ }
- if (starting != null) {
- kept = mainStack.ensureActivityConfigurationLocked(starting, changes);
- // And we need to make sure at this point that all other activities
- // are made visible with the correct configuration.
- mStackSupervisor.ensureActivitiesVisibleLocked(starting, changes);
+ if (starting != null) {
+ kept = mainStack.ensureActivityConfigurationLocked(starting, changes);
+ // And we need to make sure at this point that all other activities
+ // are made visible with the correct configuration.
+ mStackSupervisor.ensureActivitiesVisibleLocked(starting, changes);
+ }
}
if (values != null && mWindowManager != null) {
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
similarity index 98%
rename from services/java/com/android/server/am/ActivityRecord.java
rename to services/core/java/com/android/server/am/ActivityRecord.java
index 49f29fe..a27288a 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -21,6 +21,7 @@
import com.android.internal.app.ResolverActivity;
import com.android.server.AttributeCache;
import com.android.server.am.ActivityStack.ActivityState;
+import com.android.server.am.ActivityStackSupervisor.ActivityContainer;
import android.app.ActivityOptions;
import android.app.ResultInfo;
@@ -138,11 +139,13 @@
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>();
String stringName; // for caching of toString().
private boolean inHistory; // are we in the history stack?
final ActivityStackSupervisor mStackSupervisor;
+ ActivityContainer mInitialActivityContainer;
void dump(PrintWriter pw, String prefix) {
final long now = SystemClock.uptimeMillis();
@@ -347,7 +350,8 @@
int _launchedFromUid, String _launchedFromPackage, Intent _intent, String _resolvedType,
ActivityInfo aInfo, Configuration _configuration,
ActivityRecord _resultTo, String _resultWho, int _reqCode,
- boolean _componentSpecified, ActivityStackSupervisor supervisor) {
+ boolean _componentSpecified, ActivityStackSupervisor supervisor,
+ ActivityContainer container) {
service = _service;
appToken = new Token(this);
info = aInfo;
@@ -378,6 +382,7 @@
idle = false;
hasBeenLaunched = false;
mStackSupervisor = supervisor;
+ mInitialActivityContainer = container;
// This starts out true, since the initial state of an activity
// is that we have everything, and we shouldn't never consider it
@@ -481,7 +486,7 @@
void setTask(TaskRecord newTask, ThumbnailHolder newThumbHolder, boolean isRoot) {
if (task != null && task.removeActivity(this)) {
if (task != newTask) {
- mStackSupervisor.removeTask(task);
+ task.stack.removeTask(task);
} else {
Slog.d(TAG, "!!! REMOVE THIS LOG !!! setTask: nearly removed stack=" +
(newTask == null ? null : newTask.stack));
diff --git a/services/java/com/android/server/am/ActivityResult.java b/services/core/java/com/android/server/am/ActivityResult.java
similarity index 100%
rename from services/java/com/android/server/am/ActivityResult.java
rename to services/core/java/com/android/server/am/ActivityResult.java
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
similarity index 97%
rename from services/java/com/android/server/am/ActivityStack.java
rename to services/core/java/com/android/server/am/ActivityStack.java
index e9c78a7..d689a29 100755
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -39,6 +39,7 @@
import com.android.internal.os.BatteryStatsImpl;
import com.android.server.Watchdog;
import com.android.server.am.ActivityManagerService.ItemMatcher;
+import com.android.server.am.ActivityStackSupervisor.ActivityContainer;
import com.android.server.wm.AppTransition;
import com.android.server.wm.TaskGroup;
import com.android.server.wm.WindowManagerService;
@@ -52,7 +53,6 @@
import android.app.ResultInfo;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.ComponentName;
-import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
@@ -139,8 +139,6 @@
final ActivityManagerService mService;
final WindowManagerService mWindowManager;
- final Context mContext;
-
/**
* The back history of all previous (and possibly still
* running) activities. It contains #TaskRecord objects.
@@ -229,6 +227,11 @@
int mCurrentUser;
final int mStackId;
+ final ActivityContainer mActivityContainer;
+ /** The other stacks, in order, on the attached display. Updated at attach/detach time. */
+ ArrayList<ActivityStack> mStacks;
+ /** The attached Display's unique identifier, or -1 if detached */
+ int mDisplayId;
/** Run all ActivityStacks through this */
final ActivityStackSupervisor mStackSupervisor;
@@ -319,7 +322,7 @@
}
}
- private int numActivities() {
+ int numActivities() {
int count = 0;
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
count += mTaskHistory.get(taskNdx).mActivities.size();
@@ -327,14 +330,14 @@
return count;
}
- ActivityStack(ActivityManagerService service, Context context, Looper looper, int stackId) {
- mHandler = new ActivityStackHandler(looper);
- mService = service;
- mWindowManager = service.mWindowManager;
- mStackSupervisor = service.mStackSupervisor;
- mContext = context;
- mStackId = stackId;
- mCurrentUser = service.mCurrentUserId;
+ ActivityStack(ActivityStackSupervisor.ActivityContainer activityContainer) {
+ mActivityContainer = activityContainer;
+ mStackSupervisor = activityContainer.getOuter();
+ mService = mStackSupervisor.mService;
+ mHandler = new ActivityStackHandler(mService.mHandler.getLooper());
+ mWindowManager = mService.mWindowManager;
+ mStackId = activityContainer.mStackId;
+ mCurrentUser = mService.mCurrentUserId;
}
boolean okToShow(ActivityRecord r) {
@@ -436,25 +439,6 @@
return null;
}
- boolean containsApp(ProcessRecord app) {
- if (app == null) {
- return false;
- }
- 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;
- }
- if (r.app == app) {
- return true;
- }
- }
- }
- return false;
- }
-
final boolean updateLRUListLocked(ActivityRecord r) {
final boolean hadit = mLRUActivities.remove(r);
mLRUActivities.add(r);
@@ -465,6 +449,25 @@
return mStackId == HOME_STACK_ID;
}
+ final boolean isOnHomeDisplay() {
+ return isAttached() &&
+ mActivityContainer.mActivityDisplay.mDisplayId == Display.DEFAULT_DISPLAY;
+ }
+
+ final void moveToFront() {
+ if (isAttached()) {
+ if (isOnHomeDisplay()) {
+ mStackSupervisor.moveHomeStack(isHomeStack());
+ }
+ mStacks.remove(this);
+ mStacks.add(this);
+ }
+ }
+
+ final boolean isAttached() {
+ return mStacks != null;
+ }
+
/**
* Returns the top activity in any existing task matching the given
* Intent. Returns null if no such task is found.
@@ -1264,7 +1267,8 @@
ActivityOptions.abort(options);
if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: No more activities go home");
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
- return mStackSupervisor.resumeHomeActivity(prev);
+ // Only resume home if on home display
+ return isOnHomeDisplay() && mStackSupervisor.resumeHomeActivity(prev);
}
next.delayedResume = false;
@@ -1287,25 +1291,17 @@
if (prevTask != null && prevTask.mOnTopOfHome && prev.finishing && prev.frontOfTask) {
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
if (prevTask == nextTask) {
- ArrayList<ActivityRecord> activities = prevTask.mActivities;
- final int numActivities = activities.size();
- for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
- final ActivityRecord r = activities.get(activityNdx);
- // r is usually the same as next, but what if two activities were launched
- // before prev finished?
- if (!r.finishing) {
- r.frontOfTask = true;
- break;
- }
- }
+ prevTask.setFrontOfTask();
} else if (prevTask != topTask()) {
// This task is going away but it was supposed to return to the home task.
// Now the task above it has to return to the home task instead.
final int taskNdx = mTaskHistory.indexOf(prevTask) + 1;
mTaskHistory.get(taskNdx).mOnTopOfHome = true;
} else {
- if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Launching home next");
- return mStackSupervisor.resumeHomeActivity(prev);
+ if (DEBUG_STATES && isOnHomeDisplay()) Slog.d(TAG,
+ "resumeTopActivityLocked: Launching home next");
+ // Only resume home if on home display
+ return isOnHomeDisplay() && mStackSupervisor.resumeHomeActivity(prev);
}
}
@@ -1667,10 +1663,14 @@
private void insertTaskAtTop(TaskRecord task) {
// If this is being moved to the top by another activity or being launched from the home
// activity, set mOnTopOfHome accordingly.
- ActivityStack lastStack = mStackSupervisor.getLastStack();
- final boolean fromHome = lastStack == null ? true : lastStack.isHomeStack();
- if (!isHomeStack() && (fromHome || topTask() != task)) {
- task.mOnTopOfHome = fromHome;
+ if (isOnHomeDisplay()) {
+ ActivityStack lastStack = mStackSupervisor.getLastStack();
+ final boolean fromHome = lastStack.isHomeStack();
+ if (!isHomeStack() && (fromHome || topTask() != task)) {
+ task.mOnTopOfHome = fromHome;
+ }
+ } else {
+ task.mOnTopOfHome = false;
}
mTaskHistory.remove(task);
@@ -1749,9 +1749,9 @@
if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task,
new RuntimeException("here").fillInStackTrace());
task.addActivityToTop(r);
+ task.setFrontOfTask();
r.putInHistory();
- r.frontOfTask = newTask;
if (!isHomeStack() || numActivities() > 0) {
// We want to show the starting preview window if we are
// switching to a new task, or the next activity's process is
@@ -2412,15 +2412,12 @@
final ArrayList<ActivityRecord> activities = r.task.mActivities;
final int index = activities.indexOf(r);
if (index < (activities.size() - 1)) {
- ActivityRecord next = activities.get(index+1);
- if (r.frontOfTask) {
- // The next activity is now the front of the task.
- next.frontOfTask = true;
- }
+ r.task.setFrontOfTask();
if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
// If the caller asked that this activity (and all above it)
// be cleared when the task is reset, don't lose that information,
// but propagate it up to the next activity.
+ ActivityRecord next = activities.get(index+1);
next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
}
}
@@ -2599,7 +2596,7 @@
int res = mStackSupervisor.startActivityLocked(srec.app.thread, destIntent,
null, aInfo, parent.appToken, null,
0, -1, parent.launchedFromUid, parent.launchedFromPackage,
- 0, null, true, null);
+ 0, null, true, null, null);
foundParentInTask = res == ActivityManager.START_SUCCESS;
} catch (RemoteException e) {
foundParentInTask = false;
@@ -2677,7 +2674,8 @@
r.finishLaunchTickingLocked();
}
- final void removeActivityFromHistoryLocked(ActivityRecord r) {
+ private void removeActivityFromHistoryLocked(ActivityRecord r) {
+ mStackSupervisor.removeChildActivityContainers(r);
finishActivityResultsLocked(r, Activity.RESULT_CANCELED, null);
r.makeFinishing();
if (DEBUG_ADD_REMOVE) {
@@ -2692,7 +2690,7 @@
if (mStackSupervisor.isFrontStack(this) && task == topTask() && task.mOnTopOfHome) {
mStackSupervisor.moveHomeToTop();
}
- mStackSupervisor.removeTask(task);
+ removeTask(task);
}
r.takeFromHistory();
removeTimeoutsForActivityLocked(r);
@@ -3051,7 +3049,7 @@
return;
}
- mStackSupervisor.moveHomeStack(isHomeStack());
+ moveToFront();
// Shift all activities with this task up to the top
// of the stack, keeping them in the same internal order.
@@ -3160,7 +3158,7 @@
}
final TaskRecord task = mResumedActivity != null ? mResumedActivity.task : null;
- if (task == tr && task.mOnTopOfHome || numTasks <= 1) {
+ if (task == tr && tr.mOnTopOfHome || numTasks <= 1 && isOnHomeDisplay()) {
tr.mOnTopOfHome = false;
return mStackSupervisor.resumeHomeActivity(null);
}
@@ -3321,6 +3319,8 @@
r.startFreezingScreenLocked(r.app, 0);
+ mStackSupervisor.removeChildActivityContainers(r);
+
try {
if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG,
(andResume ? "Relaunching to RESUMED " : "Relaunching to PAUSED ")
@@ -3353,14 +3353,20 @@
for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = activities.get(activityNdx);
if (r.appToken == token) {
- return true;
+ return true;
}
if (r.fullscreen && !r.finishing) {
return false;
}
}
}
- return true;
+ final ActivityRecord r = ActivityRecord.forToken(token);
+ if (r == null) {
+ return false;
+ }
+ if (r.finishing) Slog.e(TAG, "willActivityBeVisibleLocked: Returning false,"
+ + " would have returned true for r=" + r);
+ return !r.finishing;
}
void closeSystemDialogsLocked() {
@@ -3599,14 +3605,30 @@
return starting;
}
- boolean removeTask(TaskRecord task) {
+ void removeTask(TaskRecord task) {
+ mWindowManager.removeTask(task.taskId);
+ final ActivityRecord r = mResumedActivity;
+ if (r != null && r.task == task) {
+ mResumedActivity = null;
+ }
+
final int taskNdx = mTaskHistory.indexOf(task);
final int topTaskNdx = mTaskHistory.size() - 1;
if (task.mOnTopOfHome && taskNdx < topTaskNdx) {
mTaskHistory.get(taskNdx + 1).mOnTopOfHome = true;
}
mTaskHistory.remove(task);
- return mTaskHistory.isEmpty();
+
+ if (mTaskHistory.isEmpty()) {
+ if (DEBUG_STACK) Slog.i(TAG, "removeTask: moving to back stack=" + this);
+ if (isOnHomeDisplay()) {
+ mStackSupervisor.moveHomeStack(!isHomeStack());
+ }
+ if (mStacks != null) {
+ mStacks.remove(this);
+ mStacks.add(0, this);
+ }
+ }
}
TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent, boolean toTop) {
diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
similarity index 71%
rename from services/java/com/android/server/am/ActivityStackSupervisor.java
rename to services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 483b4a0..13616b3 100644
--- a/services/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -34,8 +34,11 @@
import android.app.Activity;
import android.app.ActivityManager;
+import android.app.ActivityManager.StackInfo;
import android.app.ActivityOptions;
import android.app.AppGlobals;
+import android.app.IActivityContainer;
+import android.app.IActivityContainerCallback;
import android.app.IActivityManager;
import android.app.IApplicationThread;
import android.app.IThumbnailReceiver;
@@ -53,6 +56,11 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
+import android.graphics.Point;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManager.DisplayListener;
+import android.hardware.display.DisplayManagerGlobal;
+import android.hardware.display.VirtualDisplay;
import android.os.Binder;
import android.os.Bundle;
import android.os.Debug;
@@ -68,22 +76,26 @@
import android.os.UserHandle;
import android.util.EventLog;
import android.util.Slog;
-import android.util.SparseIntArray;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
+import android.view.Display;
+import android.view.DisplayInfo;
+import android.view.Surface;
import com.android.internal.app.HeavyWeightSwitcherActivity;
import com.android.internal.os.TransferPipe;
import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
import com.android.server.am.ActivityStack.ActivityState;
-import com.android.server.wm.StackBox;
import com.android.server.wm.WindowManagerService;
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;
-public final class ActivityStackSupervisor {
+public final class ActivityStackSupervisor implements DisplayListener {
static final boolean DEBUG = ActivityManagerService.DEBUG || false;
static final boolean DEBUG_ADD_REMOVE = DEBUG || false;
static final boolean DEBUG_APP = DEBUG || false;
@@ -107,19 +119,23 @@
static final int RESUME_TOP_ACTIVITY_MSG = FIRST_SUPERVISOR_STACK_MSG + 2;
static final int SLEEP_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 3;
static final int LAUNCH_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 4;
+ static final int HANDLE_DISPLAY_ADDED = FIRST_SUPERVISOR_STACK_MSG + 5;
+ static final int HANDLE_DISPLAY_CHANGED = FIRST_SUPERVISOR_STACK_MSG + 6;
+ static final int HANDLE_DISPLAY_REMOVED = FIRST_SUPERVISOR_STACK_MSG + 7;
+
+ private final static String VIRTUAL_DISPLAY_BASE_NAME = "ActivityViewVirtualDisplay";
// For debugging to make sure the caller when acquiring/releasing our
// wake lock is the system process.
static final boolean VALIDATE_WAKE_LOCK_CALLER = false;
final ActivityManagerService mService;
- final Context mContext;
- final Looper mLooper;
final ActivityStackSupervisorHandler mHandler;
/** Short cut */
WindowManagerService mWindowManager;
+ DisplayManager mDisplayManager;
/** Dismiss the keyguard after the next activity is displayed? */
boolean mDismissKeyguardOnNextActivity = false;
@@ -134,22 +150,17 @@
/** The current user */
private int mCurrentUser;
- /** The stack containing the launcher app */
+ /** The stack containing the launcher app. Assumed to always be attached to
+ * Display.DEFAULT_DISPLAY. */
private ActivityStack mHomeStack;
- /** The non-home stack currently receiving input or launching the next activity. If home is
- * in front then mHomeStack overrides mFocusedStack.
- * DO NOT ACCESS DIRECTLY - It may be null, use getFocusedStack() */
+ /** The stack currently receiving input or launching the next activity. */
private ActivityStack mFocusedStack;
- /** All the non-launcher stacks */
- private ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>();
-
- private static final int STACK_STATE_HOME_IN_FRONT = 0;
- private static final int STACK_STATE_HOME_TO_BACK = 1;
- private static final int STACK_STATE_HOME_IN_BACK = 2;
- private static final int STACK_STATE_HOME_TO_FRONT = 3;
- private int mStackState = STACK_STATE_HOME_IN_FRONT;
+ /** If this is the same as mFocusedStack then the activity on the top of the focused stack has
+ * been resumed. If stacks are changing position this will hold the old stack until the new
+ * stack becomes resumed after which it will be set to mFocusedStack. */
+ private ActivityStack mLastFocusedStack;
/** List of activities that are waiting for a new activity to become visible before completing
* whatever operation they are supposed to do. */
@@ -206,14 +217,19 @@
/** Stack id of the front stack when user switched, indexed by userId. */
SparseIntArray mUserStackInFront = new SparseIntArray(2);
- public ActivityStackSupervisor(ActivityManagerService service, Context context,
- Looper looper) {
+ // TODO: Add listener for removal of references.
+ /** Mapping from (ActivityStack/TaskStack).mStackId to their current state */
+ SparseArray<WeakReference<ActivityContainer>> mActivityContainers =
+ new SparseArray<WeakReference<ActivityContainer>>();
+
+ /** Mapping from displayId to display current state */
+ private SparseArray<ActivityDisplay> mActivityDisplays = new SparseArray<ActivityDisplay>();
+
+ public ActivityStackSupervisor(ActivityManagerService service) {
mService = service;
- mContext = context;
- mLooper = looper;
- PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+ PowerManager pm = (PowerManager)mService.mContext.getSystemService(Context.POWER_SERVICE);
mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
- mHandler = new ActivityStackSupervisorHandler(looper);
+ mHandler = new ActivityStackSupervisorHandler(mService.mHandler.getLooper());
if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
throw new IllegalStateException("Calling must be system uid");
}
@@ -223,9 +239,23 @@
}
void setWindowManager(WindowManagerService wm) {
- mWindowManager = wm;
- mHomeStack = new ActivityStack(mService, mContext, mLooper, HOME_STACK_ID);
- mStacks.add(mHomeStack);
+ synchronized (mService) {
+ mWindowManager = wm;
+
+ mDisplayManager =
+ (DisplayManager)mService.mContext.getSystemService(Context.DISPLAY_SERVICE);
+ mDisplayManager.registerDisplayListener(this, null);
+
+ Display[] displays = mDisplayManager.getDisplays();
+ for (int displayNdx = displays.length - 1; displayNdx >= 0; --displayNdx) {
+ final int displayId = displays[displayNdx].getDisplayId();
+ ActivityDisplay activityDisplay = new ActivityDisplay(displayId);
+ mActivityDisplays.put(displayId, activityDisplay);
+ }
+
+ createStackOnDisplay(null, HOME_STACK_ID, Display.DEFAULT_DISPLAY);
+ mHomeStack = mFocusedStack = mLastFocusedStack = getStack(HOME_STACK_ID);
+ }
}
void dismissKeyguard() {
@@ -237,43 +267,38 @@
}
ActivityStack getFocusedStack() {
- if (mFocusedStack == null) {
- return mHomeStack;
- }
- switch (mStackState) {
- case STACK_STATE_HOME_IN_FRONT:
- case STACK_STATE_HOME_TO_FRONT:
- return mHomeStack;
- case STACK_STATE_HOME_IN_BACK:
- case STACK_STATE_HOME_TO_BACK:
- default:
- return mFocusedStack;
- }
+ return mFocusedStack;
}
ActivityStack getLastStack() {
- switch (mStackState) {
- case STACK_STATE_HOME_IN_FRONT:
- case STACK_STATE_HOME_TO_BACK:
- return mHomeStack;
- case STACK_STATE_HOME_TO_FRONT:
- case STACK_STATE_HOME_IN_BACK:
- default:
- return mFocusedStack;
- }
+ return mLastFocusedStack;
}
+ // TODO: Split into two methods isFrontStack for any visible stack and isFrontmostStack for the
+ // top of all visible stacks.
boolean isFrontStack(ActivityStack stack) {
- return !(stack.isHomeStack() ^ getFocusedStack().isHomeStack());
+ ArrayList<ActivityStack> stacks = stack.mStacks;
+ if (stacks != null && !stacks.isEmpty()) {
+ return stack == stacks.get(stacks.size() - 1);
+ }
+ return false;
}
void moveHomeStack(boolean toFront) {
- final boolean homeInFront = isFrontStack(mHomeStack);
- if (homeInFront ^ toFront) {
- if (DEBUG_STACK) Slog.d(TAG, "moveHomeTask: mStackState old=" +
- stackStateToString(mStackState) + " new=" + stackStateToString(homeInFront ?
- STACK_STATE_HOME_TO_BACK : STACK_STATE_HOME_TO_FRONT));
- mStackState = homeInFront ? STACK_STATE_HOME_TO_BACK : STACK_STATE_HOME_TO_FRONT;
+ ArrayList<ActivityStack> stacks = mHomeStack.mStacks;
+ int topNdx = stacks.size() - 1;
+ if (topNdx <= 0) {
+ return;
+ }
+ ActivityStack topStack = stacks.get(topNdx);
+ final boolean homeInFront = topStack == mHomeStack;
+ if (homeInFront != toFront) {
+ mLastFocusedStack = topStack;
+ stacks.remove(mHomeStack);
+ stacks.add(toFront ? topNdx : 0, mHomeStack);
+ mFocusedStack = stacks.get(topNdx);
+ if (DEBUG_STACK) Slog.d(TAG, "moveHomeTask: topStack old=" + topStack + " new="
+ + mFocusedStack);
}
}
@@ -301,21 +326,29 @@
}
TaskRecord anyTaskForIdLocked(int id) {
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- ActivityStack stack = mStacks.get(stackNdx);
- TaskRecord task = stack.taskForIdLocked(id);
- if (task != null) {
- return task;
+ int numDisplays = mActivityDisplays.size();
+ for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+ ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ ActivityStack stack = stacks.get(stackNdx);
+ TaskRecord task = stack.taskForIdLocked(id);
+ if (task != null) {
+ return task;
+ }
}
}
return null;
}
ActivityRecord isInAnyStackLocked(IBinder token) {
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityRecord r = mStacks.get(stackNdx).isInStackLocked(token);
- if (r != null) {
- return r;
+ int numDisplays = mActivityDisplays.size();
+ for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+ ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityRecord r = stacks.get(stackNdx).isInStackLocked(token);
+ if (r != null) {
+ return r;
+ }
}
}
return null;
@@ -331,26 +364,6 @@
return mCurTaskId;
}
- void removeTask(TaskRecord task) {
- mWindowManager.removeTask(task.taskId);
- final ActivityStack stack = task.stack;
- final ActivityRecord r = stack.mResumedActivity;
- if (r != null && r.task == task) {
- stack.mResumedActivity = null;
- }
- if (stack.removeTask(task) && !stack.isHomeStack()) {
- if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing stack " + stack);
- mStacks.remove(stack);
- final int stackId = stack.mStackId;
- final int nextStackId = mWindowManager.removeStack(stackId);
- // TODO: Perhaps we need to let the ActivityManager determine the next focus...
- if (mFocusedStack == null || mFocusedStack.mStackId == stackId) {
- // If this is the last app stack, set mFocusedStack to null.
- mFocusedStack = nextStackId == HOME_STACK_ID ? null : getStack(nextStackId);
- }
- }
- }
-
ActivityRecord resumedAppLocked() {
ActivityStack stack = getFocusedStack();
if (stack == null) {
@@ -366,29 +379,29 @@
return resumedActivity;
}
- boolean attachApplicationLocked(ProcessRecord app, boolean headless) throws Exception {
- boolean didSomething = false;
+ boolean attachApplicationLocked(ProcessRecord app) throws Exception {
final String processName = app.processName;
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- if (!isFrontStack(stack)) {
- continue;
- }
- ActivityRecord hr = stack.topRunningActivityLocked(null);
- if (hr != null) {
- if (hr.app == null && app.uid == hr.info.applicationInfo.uid
- && processName.equals(hr.processName)) {
- try {
- if (headless) {
- Slog.e(TAG, "Starting activities not supported on headless device: "
- + hr);
- } else if (realStartActivityLocked(hr, app, true, true)) {
- didSomething = true;
+ boolean didSomething = false;
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+ if (!isFrontStack(stack)) {
+ continue;
+ }
+ ActivityRecord hr = stack.topRunningActivityLocked(null);
+ if (hr != null) {
+ if (hr.app == null && app.uid == hr.info.applicationInfo.uid
+ && processName.equals(hr.processName)) {
+ try {
+ if (realStartActivityLocked(hr, app, true, true)) {
+ didSomething = true;
+ }
+ } catch (Exception e) {
+ Slog.w(TAG, "Exception in new application when starting activity "
+ + hr.intent.getComponent().flattenToShortString(), e);
+ throw e;
}
- } catch (Exception e) {
- Slog.w(TAG, "Exception in new application when starting activity "
- + hr.intent.getComponent().flattenToShortString(), e);
- throw e;
}
}
}
@@ -400,53 +413,54 @@
}
boolean allResumedActivitiesIdle() {
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- if (!isFrontStack(stack)) {
- continue;
- }
- final ActivityRecord resumedActivity = stack.mResumedActivity;
- if (resumedActivity == null || !resumedActivity.idle) {
- return false;
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+ if (!isFrontStack(stack) || stack.numActivities() == 0) {
+ continue;
+ }
+ final ActivityRecord resumedActivity = stack.mResumedActivity;
+ if (resumedActivity == null || !resumedActivity.idle) {
+ if (DEBUG_STATES) Slog.d(TAG, "allResumedActivitiesIdle: stack="
+ + stack.mStackId + " " + resumedActivity + " not idle");
+ return false;
+ }
}
}
return true;
}
boolean allResumedActivitiesComplete() {
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- if (isFrontStack(stack)) {
- final ActivityRecord r = stack.mResumedActivity;
- if (r != null && r.state != ActivityState.RESUMED) {
- return false;
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+ if (isFrontStack(stack)) {
+ final ActivityRecord r = stack.mResumedActivity;
+ if (r != null && r.state != ActivityState.RESUMED) {
+ return false;
+ }
}
}
}
// TODO: Not sure if this should check if all Paused are complete too.
- switch (mStackState) {
- case STACK_STATE_HOME_TO_BACK:
- if (DEBUG_STACK) Slog.d(TAG, "allResumedActivitiesComplete: mStackState old=" +
- stackStateToString(STACK_STATE_HOME_TO_BACK) + " new=" +
- stackStateToString(STACK_STATE_HOME_IN_BACK));
- mStackState = STACK_STATE_HOME_IN_BACK;
- break;
- case STACK_STATE_HOME_TO_FRONT:
- if (DEBUG_STACK) Slog.d(TAG, "allResumedActivitiesComplete: mStackState old=" +
- stackStateToString(STACK_STATE_HOME_TO_FRONT) + " new=" +
- stackStateToString(STACK_STATE_HOME_IN_FRONT));
- mStackState = STACK_STATE_HOME_IN_FRONT;
- break;
- }
+ if (DEBUG_STACK) Slog.d(TAG,
+ "allResumedActivitiesComplete: mLastFocusedStack changing from=" +
+ mLastFocusedStack + " to=" + mFocusedStack);
+ mLastFocusedStack = mFocusedStack;
return true;
}
boolean allResumedActivitiesVisible() {
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- final ActivityRecord r = stack.mResumedActivity;
- if (r != null && (!r.nowVisible || r.waitingVisible)) {
- return false;
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityRecord r = stack.mResumedActivity;
+ if (r != null && (!r.nowVisible || r.waitingVisible)) {
+ return false;
+ }
}
}
return true;
@@ -459,13 +473,16 @@
*/
boolean pauseBackStacks(boolean userLeaving) {
boolean someActivityPaused = false;
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- if (!isFrontStack(stack) && stack.mResumedActivity != null) {
- if (DEBUG_STATES) Slog.d(TAG, "pauseBackStacks: stack=" + stack +
- " mResumedActivity=" + stack.mResumedActivity);
- stack.startPausingLocked(userLeaving, false);
- someActivityPaused = true;
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+ if (!isFrontStack(stack) && stack.mResumedActivity != null) {
+ if (DEBUG_STATES) Slog.d(TAG, "pauseBackStacks: stack=" + stack +
+ " mResumedActivity=" + stack.mResumedActivity);
+ stack.startPausingLocked(userLeaving, false);
+ someActivityPaused = true;
+ }
}
}
return someActivityPaused;
@@ -473,17 +490,20 @@
boolean allPausedActivitiesComplete() {
boolean pausing = true;
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- final ActivityRecord r = stack.mPausingActivity;
- if (r != null && r.state != ActivityState.PAUSED
- && r.state != ActivityState.STOPPED
- && r.state != ActivityState.STOPPING) {
- if (DEBUG_STATES) {
- Slog.d(TAG, "allPausedActivitiesComplete: r=" + r + " state=" + r.state);
- pausing = false;
- } else {
- return false;
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityRecord r = stack.mPausingActivity;
+ if (r != null && r.state != ActivityState.PAUSED
+ && r.state != ActivityState.STOPPED
+ && r.state != ActivityState.STOPPING) {
+ if (DEBUG_STATES) {
+ Slog.d(TAG, "allPausedActivitiesComplete: r=" + r + " state=" + r.state);
+ pausing = false;
+ } else {
+ return false;
+ }
}
}
}
@@ -525,8 +545,10 @@
return r;
}
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
+ // Return to the home stack.
+ final ArrayList<ActivityStack> stacks = mHomeStack.mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
if (stack != focusedStack && isFrontStack(stack)) {
r = stack.topRunningActivityLocked(null);
if (r != null) {
@@ -542,15 +564,19 @@
ActivityRecord r = null;
// Gather all of the running tasks for each stack into runningTaskLists.
- final int numStacks = mStacks.size();
- ArrayList<RunningTaskInfo>[] runningTaskLists = new ArrayList[numStacks];
- for (int stackNdx = numStacks - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- ArrayList<RunningTaskInfo> stackTaskList = new ArrayList<RunningTaskInfo>();
- runningTaskLists[stackNdx] = stackTaskList;
- final ActivityRecord ar = stack.getTasksLocked(receiver, pending, stackTaskList);
- if (isFrontStack(stack)) {
- r = ar;
+ ArrayList<ArrayList<RunningTaskInfo>> runningTaskLists =
+ new ArrayList<ArrayList<RunningTaskInfo>>();
+ final int numDisplays = mActivityDisplays.size();
+ for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+ ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+ ArrayList<RunningTaskInfo> stackTaskList = new ArrayList<RunningTaskInfo>();
+ runningTaskLists.add(stackTaskList);
+ final ActivityRecord ar = stack.getTasksLocked(receiver, pending, stackTaskList);
+ if (r == null && isFrontStack(stack)) {
+ r = ar;
+ }
}
}
@@ -559,8 +585,9 @@
while (maxNum > 0) {
long mostRecentActiveTime = Long.MIN_VALUE;
ArrayList<RunningTaskInfo> selectedStackList = null;
- for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
- ArrayList<RunningTaskInfo> stackTaskList = runningTaskLists[stackNdx];
+ final int numTaskLists = runningTaskLists.size();
+ for (int stackNdx = 0; stackNdx < numTaskLists; ++stackNdx) {
+ ArrayList<RunningTaskInfo> stackTaskList = runningTaskLists.get(stackNdx);
if (!stackTaskList.isEmpty()) {
final long lastActiveTime = stackTaskList.get(0).lastActiveTime;
if (lastActiveTime > mostRecentActiveTime) {
@@ -630,14 +657,14 @@
void startHomeActivity(Intent intent, ActivityInfo aInfo) {
moveHomeToTop();
startActivityLocked(null, intent, null, aInfo, null, null, 0, 0, 0, null, 0,
- null, false, null);
+ null, false, null, null);
}
final int startActivityMayWait(IApplicationThread caller, int callingUid,
String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags, String profileFile,
ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
- Bundle options, int userId) {
+ Bundle options, int userId, IActivityContainer iContainer) {
// Refuse possible leaked file descriptors
if (intent != null && intent.hasFileDescriptors()) {
throw new IllegalArgumentException("File descriptors passed in Intent");
@@ -651,6 +678,7 @@
ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
profileFile, profileFd, userId);
+ ActivityContainer container = (ActivityContainer)iContainer;
synchronized (mService) {
int callingPid;
if (callingUid >= 0) {
@@ -662,7 +690,12 @@
callingPid = callingUid = -1;
}
- final ActivityStack stack = getFocusedStack();
+ final ActivityStack stack;
+ if (container == null || container.mStack.isOnHomeDisplay()) {
+ stack = getFocusedStack();
+ } else {
+ stack = container.mStack;
+ }
stack.mConfigWillChange = config != null
&& mService.mConfiguration.diff(config) != 0;
if (DEBUG_CONFIGURATION) Slog.v(TAG,
@@ -738,9 +771,9 @@
}
}
- int res = startActivityLocked(caller, intent, resolvedType,
- aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
- callingPackage, startFlags, options, componentSpecified, null);
+ int res = startActivityLocked(caller, intent, resolvedType, aInfo, resultTo, resultWho,
+ requestCode, callingPid, callingUid, callingPackage, startFlags, options,
+ componentSpecified, null, container);
if (stack.mConfigWillChange) {
// If the caller also wants to switch to a new configuration,
@@ -855,7 +888,7 @@
}
int res = startActivityLocked(caller, intent, resolvedTypes[i],
aInfo, resultTo, null, -1, callingPid, callingUid, callingPackage,
- 0, theseOptions, componentSpecified, outActivity);
+ 0, theseOptions, componentSpecified, outActivity, null);
if (res < 0) {
return res;
}
@@ -1079,7 +1112,7 @@
Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
String resultWho, int requestCode,
int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
- boolean componentSpecified, ActivityRecord[] outActivity) {
+ boolean componentSpecified, ActivityRecord[] outActivity, ActivityContainer container) {
int err = ActivityManager.START_SUCCESS;
ProcessRecord callerApp = null;
@@ -1214,8 +1247,8 @@
}
ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
- intent, resolvedType, aInfo, mService.mConfiguration,
- resultRecord, resultWho, requestCode, componentSpecified, this);
+ intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
+ requestCode, componentSpecified, this, container);
if (outActivity != null) {
outActivity[0] = r;
}
@@ -1263,25 +1296,35 @@
if (r.isApplicationActivity() || (task != null && task.isApplicationTask())) {
if (task != null) {
final ActivityStack taskStack = task.stack;
- if (mFocusedStack != taskStack) {
- if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
- "adjustStackFocus: Setting focused stack to r=" + r + " task=" + task);
- mFocusedStack = taskStack.isHomeStack() ? null : taskStack;
- } else {
- if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
- "adjustStackFocus: Focused stack already=" + mFocusedStack);
+ if (taskStack.isOnHomeDisplay()) {
+ if (mFocusedStack != taskStack) {
+ if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG, "adjustStackFocus: Setting " +
+ "focused stack to r=" + r + " task=" + task);
+ mFocusedStack = taskStack;
+ } else {
+ if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
+ "adjustStackFocus: Focused stack already=" + mFocusedStack);
+ }
}
return taskStack;
}
- if (mFocusedStack != null) {
+ final ActivityContainer container = r.mInitialActivityContainer;
+ if (container != null) {
+ // The first time put it on the desired stack, after this put on task stack.
+ r.mInitialActivityContainer = null;
+ return container.mStack;
+ }
+
+ if (mFocusedStack != mHomeStack) {
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
"adjustStackFocus: Have a focused stack=" + mFocusedStack);
return mFocusedStack;
}
- for (int stackNdx = mStacks.size() - 1; stackNdx > 0; --stackNdx) {
- ActivityStack stack = mStacks.get(stackNdx);
+ final ArrayList<ActivityStack> homeDisplayStacks = mHomeStack.mStacks;
+ for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = homeDisplayStacks.get(stackNdx);
if (!stack.isHomeStack()) {
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
"adjustStackFocus: Setting focused stack=" + stack);
@@ -1290,9 +1333,8 @@
}
}
- // Time to create the first app stack for this user.
- int stackId =
- mService.createStack(-1, HOME_STACK_ID, StackBox.TASK_STACK_GOES_OVER, 1.0f);
+ // Need to create an app stack for this user.
+ int stackId = createStackOnDisplay(null, getNextStackId(), Display.DEFAULT_DISPLAY);
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG, "adjustStackFocus: New stack r=" + r +
" stackId=" + stackId);
mFocusedStack = getStack(stackId);
@@ -1302,30 +1344,10 @@
}
void setFocusedStack(ActivityRecord r) {
- if (r == null) {
- return;
- }
- if (!r.isApplicationActivity() || (r.task != null && !r.task.isApplicationTask())) {
- if (mStackState != STACK_STATE_HOME_IN_FRONT) {
- if (DEBUG_STACK || DEBUG_FOCUS) Slog.d(TAG, "setFocusedStack: mStackState old=" +
- stackStateToString(mStackState) + " new=" +
- stackStateToString(STACK_STATE_HOME_TO_FRONT) +
- " Callers=" + Debug.getCallers(3));
- mStackState = STACK_STATE_HOME_TO_FRONT;
- }
- } else {
- if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
- "setFocusedStack: Setting focused stack to r=" + r + " task=" + r.task +
- " Callers=" + Debug.getCallers(3));
- final ActivityStack taskStack = r.task.stack;
- mFocusedStack = taskStack.isHomeStack() ? null : taskStack;
- if (mStackState != STACK_STATE_HOME_IN_BACK) {
- if (DEBUG_STACK) Slog.d(TAG, "setFocusedStack: mStackState old=" +
- stackStateToString(mStackState) + " new=" +
- stackStateToString(STACK_STATE_HOME_TO_BACK) +
- " Callers=" + Debug.getCallers(3));
- mStackState = STACK_STATE_HOME_TO_BACK;
- }
+ if (r != null) {
+ final boolean isHomeActivity =
+ !r.isApplicationActivity() || (r.task != null && !r.task.isApplicationTask());
+ moveHomeStack(isHomeActivity);
}
}
@@ -1452,7 +1474,7 @@
targetStack.mLastPausedActivity = null;
if (DEBUG_TASKS) Slog.d(TAG, "Bring to front target: " + targetStack
+ " from " + intentActivity);
- moveHomeStack(targetStack.isHomeStack());
+ targetStack.moveToFront();
if (intentActivity.task.intent == null) {
// This task was started because of movement of
// the activity based on affinity... now that we
@@ -1502,9 +1524,6 @@
} else {
ActivityOptions.abort(options);
}
- if (r.task == null) Slog.v(TAG,
- "startActivityUncheckedLocked: task left null",
- new RuntimeException("here").fillInStackTrace());
return ActivityManager.START_RETURN_INTENT_TO_CALLER;
}
if ((launchFlags &
@@ -1597,9 +1616,6 @@
} else {
ActivityOptions.abort(options);
}
- if (r.task == null) Slog.v(TAG,
- "startActivityUncheckedLocked: task left null",
- new RuntimeException("here").fillInStackTrace());
return ActivityManager.START_TASK_TO_FRONT;
}
}
@@ -1637,15 +1653,9 @@
// We don't need to start a new activity, and
// the client said not to do anything if that
// is the case, so this is it!
- if (r.task == null) Slog.v(TAG,
- "startActivityUncheckedLocked: task left null",
- new RuntimeException("here").fillInStackTrace());
return ActivityManager.START_RETURN_INTENT_TO_CALLER;
}
top.deliverNewIntentLocked(callingUid, r.intent);
- if (r.task == null) Slog.v(TAG,
- "startActivityUncheckedLocked: task left null",
- new RuntimeException("here").fillInStackTrace());
return ActivityManager.START_DELIVERED_TO_TOP;
}
}
@@ -1658,9 +1668,6 @@
r.requestCode, Activity.RESULT_CANCELED, null);
}
ActivityOptions.abort(options);
- if (r.task == null) Slog.v(TAG,
- "startActivityUncheckedLocked: task left null",
- new RuntimeException("here").fillInStackTrace());
return ActivityManager.START_CLASS_NOT_FOUND;
}
@@ -1671,7 +1678,7 @@
if (r.resultTo == null && !addingToTask
&& (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
targetStack = adjustStackFocus(r);
- moveHomeStack(targetStack.isHomeStack());
+ targetStack.moveToFront();
if (reuseTask == null) {
r.setTask(targetStack.createTaskRecord(getNextTaskId(),
newTaskInfo != null ? newTaskInfo : r.info,
@@ -1689,13 +1696,13 @@
== (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
// Caller wants to appear on home activity, so before starting
// their own activity we will bring home to the front.
- r.task.mOnTopOfHome = true;
+ r.task.mOnTopOfHome = r.task.stack.isOnHomeDisplay();
}
}
} else if (sourceRecord != null) {
TaskRecord sourceTask = sourceRecord.task;
targetStack = sourceTask.stack;
- moveHomeStack(targetStack.isHomeStack());
+ targetStack.moveToFront();
if (!addingToTask &&
(launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
// In this case, we are adding the activity to an existing
@@ -1713,9 +1720,6 @@
targetStack.resumeTopActivityLocked(null);
}
ActivityOptions.abort(options);
- if (r.task == null) Slog.w(TAG,
- "startActivityUncheckedLocked: task left null",
- new RuntimeException("here").fillInStackTrace());
return ActivityManager.START_DELIVERED_TO_TOP;
}
} else if (!addingToTask &&
@@ -1749,7 +1753,7 @@
// of a new task... just put it in the top task, though these days
// this case should never happen.
targetStack = adjustStackFocus(r);
- moveHomeStack(targetStack.isHomeStack());
+ targetStack.moveToFront();
ActivityRecord prev = targetStack.topActivity();
r.setTask(prev != null ? prev.task
: targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
@@ -1941,17 +1945,21 @@
boolean handleAppDiedLocked(ProcessRecord app) {
boolean hasVisibleActivities = false;
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- hasVisibleActivities |= mStacks.get(stackNdx).handleAppDiedLocked(app);
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ hasVisibleActivities |= stacks.get(stackNdx).handleAppDiedLocked(app);
+ }
}
return hasVisibleActivities;
}
void closeSystemDialogsLocked() {
- final int numStacks = mStacks.size();
- for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- stack.closeSystemDialogsLocked();
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ stacks.get(stackNdx).closeSystemDialogsLocked();
+ }
}
}
@@ -1964,11 +1972,14 @@
*/
boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
boolean didSomething = false;
- final int numStacks = mStacks.size();
- for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- if (stack.forceStopPackageLocked(name, doit, evenPersistent, userId)) {
- didSomething = true;
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ final int numStacks = stacks.size();
+ for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+ if (stack.forceStopPackageLocked(name, doit, evenPersistent, userId)) {
+ didSomething = true;
+ }
}
}
return didSomething;
@@ -1983,15 +1994,18 @@
// we don't blow away the previous app if this activity is being
// hosted by the process that is actually still the foreground.
ProcessRecord fgApp = null;
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- if (isFrontStack(stack)) {
- if (stack.mResumedActivity != null) {
- fgApp = stack.mResumedActivity.app;
- } else if (stack.mPausingActivity != null) {
- fgApp = stack.mPausingActivity.app;
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+ if (isFrontStack(stack)) {
+ if (stack.mResumedActivity != null) {
+ fgApp = stack.mResumedActivity.app;
+ } else if (stack.mPausingActivity != null) {
+ fgApp = stack.mPausingActivity.app;
+ }
+ break;
}
- break;
}
}
@@ -2015,13 +2029,16 @@
targetStack = getFocusedStack();
}
boolean result = false;
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- if (isFrontStack(stack)) {
- if (stack == targetStack) {
- result = stack.resumeTopActivityLocked(target, targetOptions);
- } else {
- stack.resumeTopActivityLocked(null);
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+ if (isFrontStack(stack)) {
+ if (stack == targetStack) {
+ result = stack.resumeTopActivityLocked(target, targetOptions);
+ } else {
+ stack.resumeTopActivityLocked(null);
+ }
}
}
}
@@ -2029,38 +2046,118 @@
}
void finishTopRunningActivityLocked(ProcessRecord app) {
- final int numStacks = mStacks.size();
- for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- stack.finishTopRunningActivityLocked(app);
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ final int numStacks = stacks.size();
+ for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+ stack.finishTopRunningActivityLocked(app);
+ }
}
}
void findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- if (mStacks.get(stackNdx).findTaskToMoveToFrontLocked(taskId, flags, options)) {
- if (DEBUG_STACK) Slog.d(TAG, "findTaskToMoveToFront: moved to front of stack=" +
- mStacks.get(stackNdx));
- return;
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ if (stacks.get(stackNdx).findTaskToMoveToFrontLocked(taskId, flags, options)) {
+ if (DEBUG_STACK) Slog.d(TAG, "findTaskToMoveToFront: moved to front of stack="
+ + stacks.get(stackNdx));
+ return;
+ }
}
}
}
ActivityStack getStack(int stackId) {
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- if (stack.getStackId() == stackId) {
- return stack;
+ WeakReference<ActivityContainer> weakReference = mActivityContainers.get(stackId);
+ if (weakReference != null) {
+ ActivityContainer activityContainer = weakReference.get();
+ if (activityContainer != null) {
+ return activityContainer.mStack;
+ } else {
+ mActivityContainers.remove(stackId);
}
}
return null;
}
ArrayList<ActivityStack> getStacks() {
- return new ArrayList<ActivityStack>(mStacks);
+ ArrayList<ActivityStack> allStacks = new ArrayList<ActivityStack>();
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ allStacks.addAll(mActivityDisplays.valueAt(displayNdx).mStacks);
+ }
+ return allStacks;
}
- int createStack() {
+ IBinder getHomeActivityToken() {
+ final ArrayList<TaskRecord> tasks = mHomeStack.getAllTasks();
+ for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = tasks.get(taskNdx);
+ if (task.isHomeTask()) {
+ final ArrayList<ActivityRecord> activities = task.mActivities;
+ for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
+ final ActivityRecord r = activities.get(activityNdx);
+ if (r.isHomeActivity()) {
+ return r.appToken;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ ActivityContainer createActivityContainer(ActivityRecord parentActivity, int stackId,
+ IActivityContainerCallback callback) {
+ ActivityContainer activityContainer = new ActivityContainer(parentActivity, stackId,
+ callback);
+ mActivityContainers.put(stackId, new WeakReference<ActivityContainer>(activityContainer));
+ if (parentActivity != null) {
+ parentActivity.mChildContainers.add(activityContainer.mStack);
+ }
+ 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 removal");
+ }
+ mActivityContainers.removeAt(ndx);
+ container.detachLocked();
+ }
+ }
+
+ private int createStackOnDisplay(ActivityRecord parentActivity, int stackId, int displayId) {
+ ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
+ if (activityDisplay == null) {
+ return -1;
+ }
+
+ ActivityContainer activityContainer =
+ createActivityContainer(parentActivity, stackId, null);
+ activityContainer.attachToDisplayLocked(activityDisplay);
+ return stackId;
+ }
+
+ int getNextStackId() {
while (true) {
if (++mLastStackId <= HOME_STACK_ID) {
mLastStackId = HOME_STACK_ID + 1;
@@ -2069,7 +2166,6 @@
break;
}
}
- mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId));
return mLastStackId;
}
@@ -2083,7 +2179,7 @@
Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId);
return;
}
- removeTask(task);
+ task.stack.removeTask(task);
stack.addTask(task, toTop);
mWindowManager.addTask(taskId, stackId, toTop);
resumeTopActivitiesLocked();
@@ -2091,15 +2187,18 @@
ActivityRecord findTaskLocked(ActivityRecord r) {
if (DEBUG_TASKS) Slog.d(TAG, "Looking for task of " + r);
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- if (!r.isApplicationActivity() && !stack.isHomeStack()) {
- if (DEBUG_TASKS) Slog.d(TAG, "Skipping stack: " + stack);
- continue;
- }
- final ActivityRecord ar = stack.findTaskLocked(r);
- if (ar != null) {
- return ar;
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+ if (!r.isApplicationActivity() && !stack.isHomeStack()) {
+ if (DEBUG_TASKS) Slog.d(TAG, "Skipping stack: " + stack);
+ continue;
+ }
+ final ActivityRecord ar = stack.findTaskLocked(r);
+ if (ar != null) {
+ return ar;
+ }
}
}
if (DEBUG_TASKS) Slog.d(TAG, "No task found");
@@ -2107,10 +2206,13 @@
}
ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityRecord ar = mStacks.get(stackNdx).findActivityLocked(intent, info);
- if (ar != null) {
- return ar;
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityRecord ar = stacks.get(stackNdx).findActivityLocked(intent, info);
+ if (ar != null) {
+ return ar;
+ }
}
}
return null;
@@ -2138,8 +2240,11 @@
final long endTime = System.currentTimeMillis() + timeout;
while (true) {
boolean cantShutdown = false;
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- cantShutdown |= mStacks.get(stackNdx).checkReadyForSleepLocked();
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ cantShutdown |= stacks.get(stackNdx).checkReadyForSleepLocked();
+ }
}
if (cantShutdown) {
long timeRemaining = endTime - System.currentTimeMillis();
@@ -2170,11 +2275,14 @@
if (mGoingToSleep.isHeld()) {
mGoingToSleep.release();
}
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- stack.awakeFromSleepingLocked();
- if (isFrontStack(stack)) {
- resumeTopActivitiesLocked();
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+ stack.awakeFromSleepingLocked();
+ if (isFrontStack(stack)) {
+ resumeTopActivitiesLocked();
+ }
}
}
mGoingToSleepActivities.clear();
@@ -2193,8 +2301,11 @@
if (!mSleepTimeout) {
boolean dontSleep = false;
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- dontSleep |= mStacks.get(stackNdx).checkReadyForSleepLocked();
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ dontSleep |= stacks.get(stackNdx).checkReadyForSleepLocked();
+ }
}
if (mStoppingActivities.size() > 0) {
@@ -2217,8 +2328,11 @@
}
}
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- mStacks.get(stackNdx).goToSleep();
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ stacks.get(stackNdx).goToSleep();
+ }
}
removeSleepTimeouts();
@@ -2245,37 +2359,45 @@
}
void handleAppCrashLocked(ProcessRecord app) {
- final int numStacks = mStacks.size();
- for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- stack.handleAppCrashLocked(app);
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ final int numStacks = stacks.size();
+ for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+ stack.handleAppCrashLocked(app);
+ }
}
}
void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
// First the front stacks. In case any are not fullscreen and are in front of home.
boolean showHomeBehindStack = false;
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- if (isFrontStack(stack)) {
- showHomeBehindStack =
- stack.ensureActivitiesVisibleLocked(starting, configChanges);
- }
- }
- // Now do back stacks.
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- if (!isFrontStack(stack)) {
- stack.ensureActivitiesVisibleLocked(starting, configChanges, showHomeBehindStack);
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ final int topStackNdx = stacks.size() - 1;
+ for (int stackNdx = topStackNdx; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+ if (stackNdx == topStackNdx) {
+ // Top stack.
+ showHomeBehindStack =
+ stack.ensureActivitiesVisibleLocked(starting, configChanges);
+ } else {
+ // Back stack.
+ stack.ensureActivitiesVisibleLocked(starting, configChanges,
+ showHomeBehindStack);
+ }
}
}
}
void scheduleDestroyAllActivities(ProcessRecord app, String reason) {
- final int numStacks = mStacks.size();
- for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- stack.scheduleDestroyActivities(app, false, reason);
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ final int numStacks = stacks.size();
+ for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+ stack.scheduleDestroyActivities(app, false, reason);
+ }
}
}
@@ -2285,8 +2407,13 @@
mCurrentUser = userId;
mStartingUsers.add(uss);
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- mStacks.get(stackNdx).switchUserLocked(userId);
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+ stack.switchUserLocked(userId);
+ mWindowManager.moveTaskToTop(stack.topTask().taskId);
+ }
}
ActivityStack stack = getStack(restoreStackId);
@@ -2294,8 +2421,13 @@
stack = mHomeStack;
}
final boolean homeInFront = stack.isHomeStack();
- moveHomeStack(homeInFront);
- mWindowManager.moveTaskToTop(stack.topTask().taskId);
+ if (stack.isOnHomeDisplay()) {
+ moveHomeStack(homeInFront);
+ mWindowManager.moveTaskToTop(stack.topTask().taskId);
+ } else {
+ // Stack was moved to another display while user was swapped out.
+ resumeHomeActivity(null);
+ }
return homeInFront;
}
@@ -2340,8 +2472,9 @@
}
void validateTopActivitiesLocked() {
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
+ // FIXME
+/* for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
final ActivityRecord r = stack.topRunningActivityLocked(null);
final ActivityState state = r == null ? ActivityState.DESTROYED : r.state;
if (isFrontStack(stack)) {
@@ -2371,23 +2504,14 @@
}
}
}
- }
-
- private static String stackStateToString(int stackState) {
- switch (stackState) {
- case STACK_STATE_HOME_IN_FRONT: return "STACK_STATE_HOME_IN_FRONT";
- case STACK_STATE_HOME_TO_BACK: return "STACK_STATE_HOME_TO_BACK";
- case STACK_STATE_HOME_IN_BACK: return "STACK_STATE_HOME_IN_BACK";
- case STACK_STATE_HOME_TO_FRONT: return "STACK_STATE_HOME_TO_FRONT";
- default: return "Unknown stackState=" + stackState;
- }
+*/
}
public void dump(PrintWriter pw, String prefix) {
pw.print(prefix); pw.print("mDismissKeyguardOnNextActivity=");
pw.println(mDismissKeyguardOnNextActivity);
pw.print(prefix); pw.print("mFocusedStack=" + mFocusedStack);
- pw.print(" mStackState="); pw.println(stackStateToString(mStackState));
+ pw.print(" mLastFocusedStack="); pw.println(mLastFocusedStack);
pw.print(prefix); pw.println("mSleepTimeout=" + mSleepTimeout);
pw.print(prefix); pw.println("mCurTaskId=" + mCurTaskId);
pw.print(prefix); pw.println("mUserStackInFront=" + mUserStackInFront);
@@ -2416,42 +2540,48 @@
boolean dumpClient, String dumpPackage) {
boolean printed = false;
boolean needSep = false;
- final int numStacks = mStacks.size();
- for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- StringBuilder stackHeader = new StringBuilder(128);
- stackHeader.append(" Stack #");
- stackHeader.append(mStacks.indexOf(stack));
- stackHeader.append(":");
- printed |= stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage, needSep,
- stackHeader.toString());
- printed |= dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false, !dumpAll,
- false, dumpPackage, true, " Running activities (most recent first):", null);
+ for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) {
+ ActivityDisplay activityDisplay = mActivityDisplays.valueAt(displayNdx);
+ pw.print("Display #"); pw.println(activityDisplay.mDisplayId);
+ ArrayList<ActivityStack> stacks = activityDisplay.mStacks;
+ final int numStacks = stacks.size();
+ for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+ StringBuilder stackHeader = new StringBuilder(128);
+ stackHeader.append(" Stack #");
+ stackHeader.append(stack.mStackId);
+ stackHeader.append(":");
+ printed |= stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage,
+ needSep, stackHeader.toString());
+ printed |= dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false,
+ !dumpAll, false, dumpPackage, true,
+ " Running activities (most recent first):", null);
- needSep = printed;
- boolean pr = printThisActivity(pw, stack.mPausingActivity, dumpPackage, needSep,
- " mPausingActivity: ");
- if (pr) {
- printed = true;
- needSep = false;
- }
- pr = printThisActivity(pw, stack.mResumedActivity, dumpPackage, needSep,
- " mResumedActivity: ");
- if (pr) {
- printed = true;
- needSep = false;
- }
- if (dumpAll) {
- pr = printThisActivity(pw, stack.mLastPausedActivity, dumpPackage, needSep,
- " mLastPausedActivity: ");
+ needSep = printed;
+ boolean pr = printThisActivity(pw, stack.mPausingActivity, dumpPackage, needSep,
+ " mPausingActivity: ");
if (pr) {
printed = true;
- needSep = true;
+ needSep = false;
}
- printed |= printThisActivity(pw, stack.mLastNoHistoryActivity, dumpPackage,
- needSep, " mLastNoHistoryActivity: ");
+ pr = printThisActivity(pw, stack.mResumedActivity, dumpPackage, needSep,
+ " mResumedActivity: ");
+ if (pr) {
+ printed = true;
+ needSep = false;
+ }
+ if (dumpAll) {
+ pr = printThisActivity(pw, stack.mLastPausedActivity, dumpPackage, needSep,
+ " mLastPausedActivity: ");
+ if (pr) {
+ printed = true;
+ needSep = true;
+ }
+ printed |= printThisActivity(pw, stack.mLastNoHistoryActivity, dumpPackage,
+ needSep, " mLastNoHistoryActivity: ");
+ }
+ needSep = printed;
}
- needSep = printed;
}
printed |= dumpHistoryList(fd, pw, mFinishingActivities, " ", "Fin", false, !dumpAll,
@@ -2568,7 +2698,9 @@
}
final void scheduleResumeTopActivities() {
- mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
+ if (!mHandler.hasMessages(RESUME_TOP_ACTIVITY_MSG)) {
+ mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
+ }
}
void removeSleepTimeouts() {
@@ -2581,6 +2713,101 @@
mHandler.sendEmptyMessageDelayed(SLEEP_TIMEOUT_MSG, SLEEP_TIMEOUT);
}
+ @Override
+ public void onDisplayAdded(int displayId) {
+ mHandler.sendMessage(mHandler.obtainMessage(HANDLE_DISPLAY_ADDED, displayId, 0));
+ }
+
+ @Override
+ public void onDisplayRemoved(int displayId) {
+ mHandler.sendMessage(mHandler.obtainMessage(HANDLE_DISPLAY_REMOVED, displayId, 0));
+ }
+
+ @Override
+ public void onDisplayChanged(int displayId) {
+ mHandler.sendMessage(mHandler.obtainMessage(HANDLE_DISPLAY_CHANGED, displayId, 0));
+ }
+
+ public void handleDisplayAddedLocked(int displayId) {
+ boolean newDisplay;
+ synchronized (mService) {
+ newDisplay = mActivityDisplays.get(displayId) == null;
+ if (newDisplay) {
+ ActivityDisplay activityDisplay = new ActivityDisplay(displayId);
+ mActivityDisplays.put(displayId, activityDisplay);
+ }
+ }
+ if (newDisplay) {
+ mWindowManager.onDisplayAdded(displayId);
+ }
+ }
+
+ public void handleDisplayRemovedLocked(int displayId) {
+ synchronized (mService) {
+ ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
+ if (activityDisplay != null) {
+ ArrayList<ActivityStack> stacks = activityDisplay.mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ stacks.get(stackNdx).mActivityContainer.detachLocked();
+ }
+ mActivityDisplays.remove(displayId);
+ }
+ }
+ mWindowManager.onDisplayRemoved(displayId);
+ }
+
+ public void handleDisplayChangedLocked(int displayId) {
+ synchronized (mService) {
+ ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
+ if (activityDisplay != null) {
+ // TODO: Update the bounds.
+ }
+ }
+ mWindowManager.onDisplayChanged(displayId);
+ }
+
+ StackInfo getStackInfo(ActivityStack stack) {
+ StackInfo info = new StackInfo();
+ mWindowManager.getStackBounds(stack.mStackId, info.bounds);
+ info.displayId = Display.DEFAULT_DISPLAY;
+ info.stackId = stack.mStackId;
+
+ ArrayList<TaskRecord> tasks = stack.getAllTasks();
+ final int numTasks = tasks.size();
+ int[] taskIds = new int[numTasks];
+ String[] taskNames = new String[numTasks];
+ for (int i = 0; i < numTasks; ++i) {
+ final TaskRecord task = tasks.get(i);
+ taskIds[i] = task.taskId;
+ taskNames[i] = task.origActivity != null ? task.origActivity.flattenToString()
+ : task.realActivity != null ? task.realActivity.flattenToString()
+ : task.getTopActivity() != null ? task.getTopActivity().packageName
+ : "unknown";
+ }
+ info.taskIds = taskIds;
+ info.taskNames = taskNames;
+ return info;
+ }
+
+ StackInfo getStackInfoLocked(int stackId) {
+ ActivityStack stack = getStack(stackId);
+ if (stack != null) {
+ return getStackInfo(stack);
+ }
+ return null;
+ }
+
+ ArrayList<StackInfo> getAllStackInfosLocked() {
+ ArrayList<StackInfo> list = new ArrayList<StackInfo>();
+ for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) {
+ ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ for (int ndx = stacks.size() - 1; ndx >= 0; --ndx) {
+ list.add(getStackInfo(stacks.get(ndx)));
+ }
+ }
+ return list;
+ }
+
private final class ActivityStackSupervisorHandler extends Handler {
public ActivityStackSupervisorHandler(Looper looper) {
@@ -2644,7 +2871,219 @@
}
}
} break;
+ case HANDLE_DISPLAY_ADDED: {
+ handleDisplayAddedLocked(msg.arg1);
+ } break;
+ case HANDLE_DISPLAY_CHANGED: {
+ handleDisplayChangedLocked(msg.arg1);
+ } break;
+ case HANDLE_DISPLAY_REMOVED: {
+ handleDisplayRemovedLocked(msg.arg1);
+ } break;
}
}
}
+
+ class ActivityContainer extends IActivityContainer.Stub {
+ final int mStackId;
+ final IActivityContainerCallback mCallback;
+ final ActivityStack mStack;
+ final ActivityRecord mParentActivity;
+ final String mIdString;
+
+ /** Display this ActivityStack is currently on. Null if not attached to a Display. */
+ ActivityDisplay mActivityDisplay;
+
+ ActivityContainer(ActivityRecord parentActivity, int stackId,
+ IActivityContainerCallback callback) {
+ synchronized (mService) {
+ mStackId = stackId;
+ mStack = new ActivityStack(this);
+ mParentActivity = parentActivity;
+ mCallback = callback;
+ mIdString = "ActivtyContainer{" + mStackId + ", parent=" + mParentActivity + "}";
+ if (DEBUG_STACK) Slog.d(TAG, "Creating " + this);
+ }
+ }
+
+ void attachToDisplayLocked(ActivityDisplay activityDisplay) {
+ if (DEBUG_STACK) Slog.d(TAG, "attachToDisplayLocked: " + this
+ + " to display=" + activityDisplay);
+ mActivityDisplay = activityDisplay;
+ mStack.mDisplayId = activityDisplay.mDisplayId;
+ mStack.mStacks = activityDisplay.mStacks;
+
+ activityDisplay.attachActivities(mStack);
+ mWindowManager.createStack(mStackId, activityDisplay.mDisplayId);
+ }
+
+ @Override
+ public void attachToDisplay(int displayId) throws RemoteException {
+ synchronized (mService) {
+ ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
+ if (activityDisplay == null) {
+ return;
+ }
+ attachToDisplayLocked(activityDisplay);
+ }
+ }
+
+ @Override
+ public int getDisplayId() throws RemoteException {
+ if (mActivityDisplay != null) {
+ return mActivityDisplay.mDisplayId;
+ }
+ return -1;
+ }
+
+ private void detachLocked() {
+ if (DEBUG_STACK) Slog.d(TAG, "detachLocked: " + this + " from display="
+ + mActivityDisplay + " Callers=" + Debug.getCallers(2));
+ if (mActivityDisplay != null) {
+ mActivityDisplay.detachActivitiesLocked(mStack);
+ mActivityDisplay = null;
+ mStack.mDisplayId = -1;
+ mStack.mStacks = null;
+ }
+ }
+
+ @Override
+ public void detachFromDisplay() throws RemoteException {
+ synchronized (mService) {
+ detachLocked();
+ }
+ }
+
+ @Override
+ public final int startActivity(Intent intent) {
+ mService.enforceNotIsolatedCaller("ActivityContainer");
+ int userId = mService.handleIncomingUser(Binder.getCallingPid(),
+ Binder.getCallingUid(), mCurrentUser, false, true, "ActivityContainer", null);
+ // TODO: Switch to user app stacks here.
+ String mimeType = intent.getType();
+ if (mimeType == null && intent.getData() != null
+ && "content".equals(intent.getData().getScheme())) {
+ mimeType = mService.getProviderMimeType(intent.getData(), userId);
+ }
+ return startActivityMayWait(null, -1, null, intent, mimeType, null, null, 0, 0, null,
+ null, null, null, null, userId, this);
+ }
+
+ @Override
+ public IBinder asBinder() {
+ return this;
+ }
+
+ @Override
+ public void attachToSurface(Surface surface, int width, int height, int density) {
+ synchronized (mService) {
+ ActivityDisplay activityDisplay =
+ new ActivityDisplay(surface, width, height, density);
+ mActivityDisplays.put(activityDisplay.mDisplayId, activityDisplay);
+ attachToDisplayLocked(activityDisplay);
+ }
+ if (DEBUG_STACK) Slog.d(TAG, "attachToSurface: " + this + " to display="
+ + mActivityDisplay);
+ }
+
+ ActivityStackSupervisor getOuter() {
+ return ActivityStackSupervisor.this;
+ }
+
+ boolean isAttached() {
+ return mActivityDisplay != null;
+ }
+
+ void getBounds(Point outBounds) {
+ if (mActivityDisplay != null) {
+ mActivityDisplay.getBounds(outBounds);
+ } else {
+ outBounds.set(0, 0);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return mIdString + (mActivityDisplay == null ? "N" : "A");
+ }
+ }
+
+ /** Exactly one of these classes per Display in the system. Capable of holding zero or more
+ * attached {@link ActivityStack}s */
+ final 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(int displayId) {
+ init(mDisplayManager.getDisplay(displayId));
+ }
+
+ ActivityDisplay(Display display) {
+ init(display);
+ }
+
+ 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) {
+ mDisplay = display;
+ mDisplayId = display.getDisplayId();
+ mDisplay.getDisplayInfo(mDisplayInfo);
+ }
+
+ void attachActivities(ActivityStack stack) {
+ if (DEBUG_STACK) Slog.v(TAG, "attachActivities: attaching " + stack + " to displayId="
+ + mDisplayId);
+ mStacks.add(stack);
+ }
+
+ void detachActivitiesLocked(ActivityStack stack) {
+ 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) {
+ mDisplay.getDisplayInfo(mDisplayInfo);
+ bounds.x = mDisplayInfo.appWidth;
+ bounds.y = mDisplayInfo.appHeight;
+ }
+
+ @Override
+ public String toString() {
+ return "ActivityDisplay={" + mDisplayId + (mVirtualDisplay == null ? "" : "V")
+ + " numStacks=" + mStacks.size() + "}";
+ }
+ }
}
diff --git a/services/java/com/android/server/am/AppBindRecord.java b/services/core/java/com/android/server/am/AppBindRecord.java
similarity index 100%
rename from services/java/com/android/server/am/AppBindRecord.java
rename to services/core/java/com/android/server/am/AppBindRecord.java
diff --git a/services/java/com/android/server/am/AppErrorDialog.java b/services/core/java/com/android/server/am/AppErrorDialog.java
similarity index 100%
rename from services/java/com/android/server/am/AppErrorDialog.java
rename to services/core/java/com/android/server/am/AppErrorDialog.java
diff --git a/services/java/com/android/server/am/AppErrorResult.java b/services/core/java/com/android/server/am/AppErrorResult.java
similarity index 100%
rename from services/java/com/android/server/am/AppErrorResult.java
rename to services/core/java/com/android/server/am/AppErrorResult.java
diff --git a/services/java/com/android/server/am/AppNotRespondingDialog.java b/services/core/java/com/android/server/am/AppNotRespondingDialog.java
similarity index 100%
rename from services/java/com/android/server/am/AppNotRespondingDialog.java
rename to services/core/java/com/android/server/am/AppNotRespondingDialog.java
diff --git a/services/java/com/android/server/am/AppWaitingForDebuggerDialog.java b/services/core/java/com/android/server/am/AppWaitingForDebuggerDialog.java
similarity index 100%
rename from services/java/com/android/server/am/AppWaitingForDebuggerDialog.java
rename to services/core/java/com/android/server/am/AppWaitingForDebuggerDialog.java
diff --git a/services/java/com/android/server/am/BackupRecord.java b/services/core/java/com/android/server/am/BackupRecord.java
similarity index 100%
rename from services/java/com/android/server/am/BackupRecord.java
rename to services/core/java/com/android/server/am/BackupRecord.java
diff --git a/services/java/com/android/server/am/BaseErrorDialog.java b/services/core/java/com/android/server/am/BaseErrorDialog.java
similarity index 100%
rename from services/java/com/android/server/am/BaseErrorDialog.java
rename to services/core/java/com/android/server/am/BaseErrorDialog.java
diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
similarity index 98%
rename from services/java/com/android/server/am/BatteryStatsService.java
rename to services/core/java/com/android/server/am/BatteryStatsService.java
index 2d59678..ff06513 100644
--- a/services/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -24,6 +24,7 @@
import android.content.pm.PackageManager;
import android.os.BatteryStats;
import android.os.Binder;
+import android.os.Handler;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Process;
@@ -54,8 +55,8 @@
private boolean mBluetoothPendingStats;
private BluetoothHeadset mBluetoothHeadset;
- BatteryStatsService(String filename) {
- mStats = new BatteryStatsImpl(filename);
+ BatteryStatsService(String filename, Handler handler) {
+ mStats = new BatteryStatsImpl(filename, handler);
}
public void publish(Context context) {
diff --git a/services/java/com/android/server/am/BroadcastFilter.java b/services/core/java/com/android/server/am/BroadcastFilter.java
similarity index 100%
rename from services/java/com/android/server/am/BroadcastFilter.java
rename to services/core/java/com/android/server/am/BroadcastFilter.java
diff --git a/services/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
similarity index 98%
rename from services/java/com/android/server/am/BroadcastQueue.java
rename to services/core/java/com/android/server/am/BroadcastQueue.java
index bfb667f..aef9e5c 100644
--- a/services/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -33,6 +33,7 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
+import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
@@ -132,7 +133,14 @@
static final int BROADCAST_INTENT_MSG = ActivityManagerService.FIRST_BROADCAST_QUEUE_MSG;
static final int BROADCAST_TIMEOUT_MSG = ActivityManagerService.FIRST_BROADCAST_QUEUE_MSG + 1;
- final Handler mHandler = new Handler() {
+ final BroadcastHandler mHandler;
+
+ private final class BroadcastHandler extends Handler {
+ public BroadcastHandler(Looper looper) {
+ super(looper, null, true);
+ }
+
+ @Override
public void handleMessage(Message msg) {
switch (msg.what) {
case BROADCAST_INTENT_MSG: {
@@ -164,9 +172,10 @@
}
}
- BroadcastQueue(ActivityManagerService service, String name, long timeoutPeriod,
- boolean allowDelayBehindServices) {
+ BroadcastQueue(ActivityManagerService service, Handler handler,
+ String name, long timeoutPeriod, boolean allowDelayBehindServices) {
mService = service;
+ mHandler = new BroadcastHandler(handler.getLooper());
mQueueName = name;
mTimeoutPeriod = timeoutPeriod;
mDelayBehindServices = allowDelayBehindServices;
diff --git a/services/java/com/android/server/am/BroadcastRecord.java b/services/core/java/com/android/server/am/BroadcastRecord.java
similarity index 100%
rename from services/java/com/android/server/am/BroadcastRecord.java
rename to services/core/java/com/android/server/am/BroadcastRecord.java
diff --git a/services/java/com/android/server/am/CompatModeDialog.java b/services/core/java/com/android/server/am/CompatModeDialog.java
similarity index 100%
rename from services/java/com/android/server/am/CompatModeDialog.java
rename to services/core/java/com/android/server/am/CompatModeDialog.java
diff --git a/services/java/com/android/server/am/CompatModePackages.java b/services/core/java/com/android/server/am/CompatModePackages.java
similarity index 97%
rename from services/java/com/android/server/am/CompatModePackages.java
rename to services/core/java/com/android/server/am/CompatModePackages.java
index 4d5577b..207d630 100644
--- a/services/java/com/android/server/am/CompatModePackages.java
+++ b/services/core/java/com/android/server/am/CompatModePackages.java
@@ -19,6 +19,7 @@
import android.content.pm.IPackageManager;
import android.content.res.CompatibilityInfo;
import android.os.Handler;
+import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.util.AtomicFile;
@@ -41,22 +42,27 @@
private static final int MSG_WRITE = ActivityManagerService.FIRST_COMPAT_MODE_MSG;
- private final Handler mHandler = new Handler() {
- @Override public void handleMessage(Message msg) {
+ private final CompatHandler mHandler;
+
+ private final class CompatHandler extends Handler {
+ public CompatHandler(Looper looper) {
+ super(looper, null, true);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_WRITE:
saveCompatModes();
break;
- default:
- super.handleMessage(msg);
- break;
}
}
};
- public CompatModePackages(ActivityManagerService service, File systemDir) {
+ public CompatModePackages(ActivityManagerService service, File systemDir, Handler handler) {
mService = service;
mFile = new AtomicFile(new File(systemDir, "packages-compat.xml"));
+ mHandler = new CompatHandler(handler.getLooper());
FileInputStream fis = null;
try {
diff --git a/services/java/com/android/server/am/ConnectionRecord.java b/services/core/java/com/android/server/am/ConnectionRecord.java
similarity index 100%
rename from services/java/com/android/server/am/ConnectionRecord.java
rename to services/core/java/com/android/server/am/ConnectionRecord.java
diff --git a/services/java/com/android/server/am/ContentProviderConnection.java b/services/core/java/com/android/server/am/ContentProviderConnection.java
similarity index 100%
rename from services/java/com/android/server/am/ContentProviderConnection.java
rename to services/core/java/com/android/server/am/ContentProviderConnection.java
diff --git a/services/java/com/android/server/am/ContentProviderRecord.java b/services/core/java/com/android/server/am/ContentProviderRecord.java
similarity index 100%
rename from services/java/com/android/server/am/ContentProviderRecord.java
rename to services/core/java/com/android/server/am/ContentProviderRecord.java
diff --git a/services/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java
similarity index 100%
rename from services/java/com/android/server/am/CoreSettingsObserver.java
rename to services/core/java/com/android/server/am/CoreSettingsObserver.java
diff --git a/services/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags
similarity index 100%
rename from services/java/com/android/server/am/EventLogTags.logtags
rename to services/core/java/com/android/server/am/EventLogTags.logtags
diff --git a/services/java/com/android/server/am/FactoryErrorDialog.java b/services/core/java/com/android/server/am/FactoryErrorDialog.java
similarity index 100%
rename from services/java/com/android/server/am/FactoryErrorDialog.java
rename to services/core/java/com/android/server/am/FactoryErrorDialog.java
diff --git a/services/java/com/android/server/am/IntentBindRecord.java b/services/core/java/com/android/server/am/IntentBindRecord.java
similarity index 100%
rename from services/java/com/android/server/am/IntentBindRecord.java
rename to services/core/java/com/android/server/am/IntentBindRecord.java
diff --git a/services/java/com/android/server/am/LaunchWarningWindow.java b/services/core/java/com/android/server/am/LaunchWarningWindow.java
similarity index 100%
rename from services/java/com/android/server/am/LaunchWarningWindow.java
rename to services/core/java/com/android/server/am/LaunchWarningWindow.java
diff --git a/services/java/com/android/server/am/NativeCrashListener.java b/services/core/java/com/android/server/am/NativeCrashListener.java
similarity index 99%
rename from services/java/com/android/server/am/NativeCrashListener.java
rename to services/core/java/com/android/server/am/NativeCrashListener.java
index 2c7f1f1..b12843b 100644
--- a/services/java/com/android/server/am/NativeCrashListener.java
+++ b/services/core/java/com/android/server/am/NativeCrashListener.java
@@ -95,8 +95,8 @@
* Daemon thread that accept()s incoming domain socket connections from debuggerd
* and processes the crash dump that is passed through.
*/
- NativeCrashListener() {
- mAm = ActivityManagerService.self();
+ NativeCrashListener(ActivityManagerService am) {
+ mAm = am;
}
@Override
diff --git a/services/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
similarity index 100%
rename from services/java/com/android/server/am/PendingIntentRecord.java
rename to services/core/java/com/android/server/am/PendingIntentRecord.java
diff --git a/services/java/com/android/server/am/PendingThumbnailsRecord.java b/services/core/java/com/android/server/am/PendingThumbnailsRecord.java
similarity index 100%
rename from services/java/com/android/server/am/PendingThumbnailsRecord.java
rename to services/core/java/com/android/server/am/PendingThumbnailsRecord.java
diff --git a/services/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
similarity index 100%
rename from services/java/com/android/server/am/ProcessList.java
rename to services/core/java/com/android/server/am/ProcessList.java
diff --git a/services/java/com/android/server/am/ProcessMemInfo.java b/services/core/java/com/android/server/am/ProcessMemInfo.java
similarity index 100%
rename from services/java/com/android/server/am/ProcessMemInfo.java
rename to services/core/java/com/android/server/am/ProcessMemInfo.java
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
similarity index 100%
rename from services/java/com/android/server/am/ProcessRecord.java
rename to services/core/java/com/android/server/am/ProcessRecord.java
diff --git a/services/java/com/android/server/am/ProcessStatsService.java b/services/core/java/com/android/server/am/ProcessStatsService.java
similarity index 100%
rename from services/java/com/android/server/am/ProcessStatsService.java
rename to services/core/java/com/android/server/am/ProcessStatsService.java
diff --git a/services/java/com/android/server/am/ProviderMap.java b/services/core/java/com/android/server/am/ProviderMap.java
similarity index 100%
rename from services/java/com/android/server/am/ProviderMap.java
rename to services/core/java/com/android/server/am/ProviderMap.java
diff --git a/services/java/com/android/server/am/ReceiverList.java b/services/core/java/com/android/server/am/ReceiverList.java
similarity index 100%
rename from services/java/com/android/server/am/ReceiverList.java
rename to services/core/java/com/android/server/am/ReceiverList.java
diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
similarity index 98%
rename from services/java/com/android/server/am/ServiceRecord.java
rename to services/core/java/com/android/server/am/ServiceRecord.java
index 80e6e94..cb04835 100644
--- a/services/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -18,7 +18,8 @@
import com.android.internal.app.ProcessStats;
import com.android.internal.os.BatteryStatsImpl;
-import com.android.server.NotificationManagerService;
+import com.android.server.LocalServices;
+import com.android.server.notification.NotificationManagerInternal;
import android.app.INotificationManager;
import android.app.Notification;
@@ -427,8 +428,8 @@
final Notification localForegroundNoti = foregroundNoti;
ams.mHandler.post(new Runnable() {
public void run() {
- NotificationManagerService nm =
- (NotificationManagerService) NotificationManager.getService();
+ NotificationManagerInternal nm = LocalServices.getService(
+ NotificationManagerInternal.class);
if (nm == null) {
return;
}
@@ -479,7 +480,7 @@
throw new RuntimeException("icon must be non-zero");
}
int[] outId = new int[1];
- nm.enqueueNotificationInternal(localPackageName, localPackageName,
+ nm.enqueueNotification(localPackageName, localPackageName,
appUid, appPid, null, localForegroundId, localForegroundNoti,
outId, userId);
} catch (RuntimeException e) {
diff --git a/services/java/com/android/server/am/StrictModeViolationDialog.java b/services/core/java/com/android/server/am/StrictModeViolationDialog.java
similarity index 100%
rename from services/java/com/android/server/am/StrictModeViolationDialog.java
rename to services/core/java/com/android/server/am/StrictModeViolationDialog.java
diff --git a/services/java/com/android/server/am/TaskAccessInfo.java b/services/core/java/com/android/server/am/TaskAccessInfo.java
similarity index 100%
rename from services/java/com/android/server/am/TaskAccessInfo.java
rename to services/core/java/com/android/server/am/TaskAccessInfo.java
diff --git a/services/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
similarity index 95%
rename from services/java/com/android/server/am/TaskRecord.java
rename to services/core/java/com/android/server/am/TaskRecord.java
index 3d568ff..9740812 100644
--- a/services/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -60,7 +60,8 @@
/** Takes on same set of values as ActivityRecord.mActivityType */
private int mTaskType;
- /** Launch the home activity when leaving this task. */
+ /** Launch the home activity when leaving this task. Will be false for tasks that are not on
+ * Display.DEFAULT_DISPLAY. */
boolean mOnTopOfHome = false;
TaskRecord(int _taskId, ActivityInfo info, Intent _intent) {
@@ -159,18 +160,33 @@
return null;
}
+ /** Call after activity movement or finish to make sure that frontOfTask is set correctly */
+ final void setFrontOfTask() {
+ boolean foundFront = false;
+ final int numActivities = mActivities.size();
+ for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
+ final ActivityRecord r = mActivities.get(activityNdx);
+ if (foundFront || r.finishing) {
+ r.frontOfTask = false;
+ } else {
+ r.frontOfTask = true;
+ // Set frontOfTask false for every following activity.
+ foundFront = true;
+ }
+ }
+ }
+
/**
- * Reorder the history stack so that the activity at the given index is
- * brought to the front.
+ * Reorder the history stack so that the passed activity is brought to the front.
*/
final void moveActivityToFrontLocked(ActivityRecord newTop) {
if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Removing and adding activity " + newTop
+ " to stack at top", new RuntimeException("here").fillInStackTrace());
- getTopActivity().frontOfTask = false;
mActivities.remove(newTop);
mActivities.add(newTop);
- newTop.frontOfTask = true;
+
+ setFrontOfTask();
}
void addActivityAtBottom(ActivityRecord r) {
diff --git a/services/java/com/android/server/am/ThumbnailHolder.java b/services/core/java/com/android/server/am/ThumbnailHolder.java
similarity index 100%
rename from services/java/com/android/server/am/ThumbnailHolder.java
rename to services/core/java/com/android/server/am/ThumbnailHolder.java
diff --git a/services/java/com/android/server/am/UriPermission.java b/services/core/java/com/android/server/am/UriPermission.java
similarity index 100%
rename from services/java/com/android/server/am/UriPermission.java
rename to services/core/java/com/android/server/am/UriPermission.java
diff --git a/services/java/com/android/server/am/UriPermissionOwner.java b/services/core/java/com/android/server/am/UriPermissionOwner.java
similarity index 100%
rename from services/java/com/android/server/am/UriPermissionOwner.java
rename to services/core/java/com/android/server/am/UriPermissionOwner.java
diff --git a/services/java/com/android/server/am/UsageStatsService.java b/services/core/java/com/android/server/am/UsageStatsService.java
similarity index 100%
rename from services/java/com/android/server/am/UsageStatsService.java
rename to services/core/java/com/android/server/am/UsageStatsService.java
diff --git a/services/java/com/android/server/am/UserStartedState.java b/services/core/java/com/android/server/am/UserStartedState.java
similarity index 100%
rename from services/java/com/android/server/am/UserStartedState.java
rename to services/core/java/com/android/server/am/UserStartedState.java
diff --git a/services/java/com/android/server/am/package.html b/services/core/java/com/android/server/am/package.html
similarity index 100%
rename from services/java/com/android/server/am/package.html
rename to services/core/java/com/android/server/am/package.html
diff --git a/services/java/com/android/server/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
similarity index 99%
rename from services/java/com/android/server/ClipboardService.java
rename to services/core/java/com/android/server/clipboard/ClipboardService.java
index 069ae23..6aa596d 100644
--- a/services/java/com/android/server/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server;
+package com.android.server.clipboard;
import android.app.ActivityManagerNative;
import android.app.AppGlobals;
diff --git a/services/java/com/android/server/connectivity/DataConnectionStats.java b/services/core/java/com/android/server/connectivity/DataConnectionStats.java
similarity index 100%
rename from services/java/com/android/server/connectivity/DataConnectionStats.java
rename to services/core/java/com/android/server/connectivity/DataConnectionStats.java
diff --git a/services/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
similarity index 100%
rename from services/java/com/android/server/connectivity/Nat464Xlat.java
rename to services/core/java/com/android/server/connectivity/Nat464Xlat.java
diff --git a/services/java/com/android/server/connectivity/PacManager.java b/services/core/java/com/android/server/connectivity/PacManager.java
similarity index 100%
rename from services/java/com/android/server/connectivity/PacManager.java
rename to services/core/java/com/android/server/connectivity/PacManager.java
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
similarity index 100%
rename from services/java/com/android/server/connectivity/Tethering.java
rename to services/core/java/com/android/server/connectivity/Tethering.java
diff --git a/services/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
similarity index 100%
rename from services/java/com/android/server/connectivity/Vpn.java
rename to services/core/java/com/android/server/connectivity/Vpn.java
diff --git a/services/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
similarity index 100%
rename from services/java/com/android/server/content/ContentService.java
rename to services/core/java/com/android/server/content/ContentService.java
diff --git a/services/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
similarity index 100%
rename from services/java/com/android/server/content/SyncManager.java
rename to services/core/java/com/android/server/content/SyncManager.java
diff --git a/services/java/com/android/server/content/SyncOperation.java b/services/core/java/com/android/server/content/SyncOperation.java
similarity index 100%
rename from services/java/com/android/server/content/SyncOperation.java
rename to services/core/java/com/android/server/content/SyncOperation.java
diff --git a/services/java/com/android/server/content/SyncQueue.java b/services/core/java/com/android/server/content/SyncQueue.java
similarity index 100%
rename from services/java/com/android/server/content/SyncQueue.java
rename to services/core/java/com/android/server/content/SyncQueue.java
diff --git a/services/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java
similarity index 100%
rename from services/java/com/android/server/content/SyncStorageEngine.java
rename to services/core/java/com/android/server/content/SyncStorageEngine.java
diff --git a/services/java/com/android/server/display/DisplayAdapter.java b/services/core/java/com/android/server/display/DisplayAdapter.java
similarity index 100%
rename from services/java/com/android/server/display/DisplayAdapter.java
rename to services/core/java/com/android/server/display/DisplayAdapter.java
diff --git a/services/java/com/android/server/display/DisplayDevice.java b/services/core/java/com/android/server/display/DisplayDevice.java
similarity index 99%
rename from services/java/com/android/server/display/DisplayDevice.java
rename to services/core/java/com/android/server/display/DisplayDevice.java
index 4161147..9ec1122 100644
--- a/services/java/com/android/server/display/DisplayDevice.java
+++ b/services/core/java/com/android/server/display/DisplayDevice.java
@@ -17,6 +17,7 @@
package com.android.server.display;
import android.graphics.Rect;
+import android.hardware.display.DisplayViewport;
import android.os.IBinder;
import android.view.Surface;
import android.view.SurfaceControl;
diff --git a/services/java/com/android/server/display/DisplayDeviceInfo.java b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
similarity index 95%
rename from services/java/com/android/server/display/DisplayDeviceInfo.java
rename to services/core/java/com/android/server/display/DisplayDeviceInfo.java
index 11c5d87..75f1f53 100644
--- a/services/java/com/android/server/display/DisplayDeviceInfo.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
@@ -16,6 +16,7 @@
package com.android.server.display;
+import android.hardware.display.DisplayViewport;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.Surface;
@@ -63,6 +64,7 @@
/**
* Flag: Indicates that the display device is owned by a particular application
* and that no other application should be able to interact with it.
+ * Should typically be used together with {@link #FLAG_OWN_CONTENT_ONLY}.
*/
public static final int FLAG_PRIVATE = 1 << 4;
@@ -78,6 +80,12 @@
public static final int FLAG_PRESENTATION = 1 << 6;
/**
+ * Flag: Only show this display's own content; do not mirror
+ * the content of another display.
+ */
+ public static final int FLAG_OWN_CONTENT_ONLY = 1 << 7;
+
+ /**
* Touch attachment: Display does not receive touch.
*/
public static final int TOUCH_NONE = 0;
@@ -297,6 +305,9 @@
if ((flags & FLAG_PRESENTATION) != 0) {
msg.append(", FLAG_PRESENTATION");
}
+ if ((flags & FLAG_OWN_CONTENT_ONLY) != 0) {
+ msg.append(", FLAG_OWN_CONTENT_ONLY");
+ }
return msg.toString();
}
}
diff --git a/services/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
similarity index 62%
rename from services/java/com/android/server/display/DisplayManagerService.java
rename to services/core/java/com/android/server/display/DisplayManagerService.java
index bcb677f..d5ee838 100644
--- a/services/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -23,14 +23,20 @@
import android.content.pm.PackageManager;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerGlobal;
+import android.hardware.display.DisplayManagerInternal;
+import android.hardware.display.DisplayViewport;
+import android.hardware.display.DisplayManagerInternal.DisplayTransactionListener;
import android.hardware.display.IDisplayManager;
import android.hardware.display.IDisplayManagerCallback;
import android.hardware.display.WifiDisplayStatus;
+import android.hardware.input.InputManagerInternal;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
+import android.os.IBinder.DeathRecipient;
import android.os.Looper;
import android.os.Message;
+import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemProperties;
@@ -41,7 +47,11 @@
import android.view.Display;
import android.view.DisplayInfo;
import android.view.Surface;
+import android.view.WindowManagerInternal;
+import com.android.server.DisplayThread;
+import com.android.server.LocalServices;
+import com.android.server.SystemService;
import com.android.server.UiThread;
import java.io.FileDescriptor;
@@ -93,7 +103,7 @@
* avoid this by making all potentially reentrant out-calls asynchronous.
* </p>
*/
-public final class DisplayManagerService extends IDisplayManager.Stub {
+public final class DisplayManagerService extends SystemService {
private static final String TAG = "DisplayManagerService";
private static final boolean DEBUG = false;
@@ -102,7 +112,6 @@
// Otherwise WFD is enabled according to the value of config_enableWifiDisplay.
private static final String FORCE_WIFI_DISPLAY_ENABLE = "persist.debug.wfd.enable";
- private static final String SYSTEM_HEADLESS = "ro.config.headless";
private static final long WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT = 10000;
private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER = 1;
@@ -115,13 +124,12 @@
private static final int DISPLAY_BLANK_STATE_BLANKED = 1;
private static final int DISPLAY_BLANK_STATE_UNBLANKED = 2;
- private final Context mContext;
- private final boolean mHeadless;
+ private Context mContext;
private final DisplayManagerHandler mHandler;
private final Handler mUiHandler;
private final DisplayAdapterListener mDisplayAdapterListener;
- private WindowManagerFuncs mWindowManagerFuncs;
- private InputManagerFuncs mInputManagerFuncs;
+ private WindowManagerInternal mWindowManagerInternal;
+ private InputManagerInternal mInputManagerInternal;
// The synchronization root for the display manager.
// This lock guards most of the display manager's state.
@@ -200,59 +208,55 @@
private final DisplayViewport mTempDefaultViewport = new DisplayViewport();
private final DisplayViewport mTempExternalTouchViewport = new DisplayViewport();
- public DisplayManagerService(Context context, Handler mainHandler) {
- mContext = context;
- mHeadless = SystemProperties.get(SYSTEM_HEADLESS).equals("1");
-
- mHandler = new DisplayManagerHandler(mainHandler.getLooper());
+ public DisplayManagerService() {
+ mHandler = new DisplayManagerHandler(DisplayThread.get().getLooper());
mUiHandler = UiThread.getHandler();
mDisplayAdapterListener = new DisplayAdapterListener();
mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);
-
- mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER);
}
- /**
- * Pauses the boot process to wait for the first display to be initialized.
- */
- public boolean waitForDefaultDisplay() {
- synchronized (mSyncRoot) {
- long timeout = SystemClock.uptimeMillis() + WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT;
- while (mLogicalDisplays.get(Display.DEFAULT_DISPLAY) == null) {
- long delay = timeout - SystemClock.uptimeMillis();
- if (delay <= 0) {
- return false;
- }
- if (DEBUG) {
- Slog.d(TAG, "waitForDefaultDisplay: waiting, timeout=" + delay);
- }
- try {
- mSyncRoot.wait(delay);
- } catch (InterruptedException ex) {
+ @Override
+ public void onCreate(Context context) {
+ mContext = context;
+ }
+
+ @Override
+ public void onStart() {
+ mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER);
+
+ publishBinderService(Context.DISPLAY_SERVICE, new BinderService(),
+ true /*allowIsolated*/);
+ publishLocalService(DisplayManagerInternal.class, new LocalService());
+ }
+
+ @Override
+ public void onBootPhase(int phase) {
+ if (phase == PHASE_WAIT_FOR_DEFAULT_DISPLAY) {
+ synchronized (mSyncRoot) {
+ long timeout = SystemClock.uptimeMillis() + WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT;
+ while (mLogicalDisplays.get(Display.DEFAULT_DISPLAY) == null) {
+ long delay = timeout - SystemClock.uptimeMillis();
+ if (delay <= 0) {
+ throw new RuntimeException("Timeout waiting for default display "
+ + "to be initialized.");
+ }
+ if (DEBUG) {
+ Slog.d(TAG, "waitForDefaultDisplay: waiting, timeout=" + delay);
+ }
+ try {
+ mSyncRoot.wait(delay);
+ } catch (InterruptedException ex) {
+ }
}
}
}
- return true;
}
- /**
- * Called during initialization to associate the display manager with the
- * window manager.
- */
- public void setWindowManager(WindowManagerFuncs windowManagerFuncs) {
+ // TODO: Use dependencies or a boot phase
+ public void windowManagerAndInputReady() {
synchronized (mSyncRoot) {
- mWindowManagerFuncs = windowManagerFuncs;
- scheduleTraversalLocked(false);
- }
- }
-
- /**
- * Called during initialization to associate the display manager with the
- * input manager.
- */
- public void setInputManager(InputManagerFuncs inputManagerFuncs) {
- synchronized (mSyncRoot) {
- mInputManagerFuncs = inputManagerFuncs;
+ mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
+ mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
scheduleTraversalLocked(false);
}
}
@@ -269,59 +273,19 @@
mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS);
}
- /**
- * Returns true if the device is headless.
- *
- * @return True if the device is headless.
- */
- public boolean isHeadless() {
- return mHeadless;
- }
-
- /**
- * Registers a display transaction listener to provide the client a chance to
- * update its surfaces within the same transaction as any display layout updates.
- *
- * @param listener The listener to register.
- */
- public void registerDisplayTransactionListener(DisplayTransactionListener listener) {
- if (listener == null) {
- throw new IllegalArgumentException("listener must not be null");
- }
-
+ private void registerDisplayTransactionListenerInternal(
+ DisplayTransactionListener listener) {
// List is self-synchronized copy-on-write.
mDisplayTransactionListeners.add(listener);
}
- /**
- * Unregisters a display transaction listener to provide the client a chance to
- * update its surfaces within the same transaction as any display layout updates.
- *
- * @param listener The listener to unregister.
- */
- public void unregisterDisplayTransactionListener(DisplayTransactionListener listener) {
- if (listener == null) {
- throw new IllegalArgumentException("listener must not be null");
- }
-
+ private void unregisterDisplayTransactionListenerInternal(
+ DisplayTransactionListener listener) {
// List is self-synchronized copy-on-write.
mDisplayTransactionListeners.remove(listener);
}
- /**
- * Overrides the display information of a particular logical display.
- * This is used by the window manager to control the size and characteristics
- * of the default display. It is expected to apply the requested change
- * to the display information synchronously so that applications will immediately
- * observe the new state.
- *
- * NOTE: This method must be the only entry point by which the window manager
- * influences the logical configuration of displays.
- *
- * @param displayId The logical display id.
- * @param info The new data to be stored.
- */
- public void setDisplayInfoOverrideFromWindowManager(
+ private void setDisplayInfoOverrideFromWindowManagerInternal(
int displayId, DisplayInfo info) {
synchronized (mSyncRoot) {
LogicalDisplay display = mLogicalDisplays.get(displayId);
@@ -334,11 +298,7 @@
}
}
- /**
- * Called by the window manager to perform traversals while holding a
- * surface flinger transaction.
- */
- public void performTraversalInTransactionFromWindowManager() {
+ private void performTraversalInTransactionFromWindowManagerInternal() {
synchronized (mSyncRoot) {
if (!mPendingTraversal) {
return;
@@ -354,10 +314,7 @@
}
}
- /**
- * Called by the power manager to blank all displays.
- */
- public void blankAllDisplaysFromPowerManager() {
+ private void blankAllDisplaysFromPowerManagerInternal() {
synchronized (mSyncRoot) {
if (mAllDisplayBlankStateFromPowerManager != DISPLAY_BLANK_STATE_BLANKED) {
mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_BLANKED;
@@ -367,10 +324,7 @@
}
}
- /**
- * Called by the power manager to unblank all displays.
- */
- public void unblankAllDisplaysFromPowerManager() {
+ private void unblankAllDisplaysFromPowerManagerInternal() {
synchronized (mSyncRoot) {
if (mAllDisplayBlankStateFromPowerManager != DISPLAY_BLANK_STATE_UNBLANKED) {
mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_UNBLANKED;
@@ -380,70 +334,40 @@
}
}
- /**
- * Returns information about the specified logical display.
- *
- * @param displayId The logical display id.
- * @return The logical display info, or null if the display does not exist. The
- * returned object must be treated as immutable.
- */
- @Override // Binder call
- public DisplayInfo getDisplayInfo(int displayId) {
- final int callingUid = Binder.getCallingUid();
- final long token = Binder.clearCallingIdentity();
- try {
- synchronized (mSyncRoot) {
- LogicalDisplay display = mLogicalDisplays.get(displayId);
- if (display != null) {
- DisplayInfo info = display.getDisplayInfoLocked();
- if (info.hasAccess(callingUid)) {
- return info;
- }
- }
- return null;
- }
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- /**
- * Returns the list of all display ids.
- */
- @Override // Binder call
- public int[] getDisplayIds() {
- final int callingUid = Binder.getCallingUid();
- final long token = Binder.clearCallingIdentity();
- try {
- synchronized (mSyncRoot) {
- final int count = mLogicalDisplays.size();
- int[] displayIds = new int[count];
- int n = 0;
- for (int i = 0; i < count; i++) {
- LogicalDisplay display = mLogicalDisplays.valueAt(i);
- DisplayInfo info = display.getDisplayInfoLocked();
- if (info.hasAccess(callingUid)) {
- displayIds[n++] = mLogicalDisplays.keyAt(i);
- }
- }
- if (n != count) {
- displayIds = Arrays.copyOfRange(displayIds, 0, n);
- }
- return displayIds;
- }
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override // Binder call
- public void registerCallback(IDisplayManagerCallback callback) {
- if (callback == null) {
- throw new IllegalArgumentException("listener must not be null");
- }
-
+ private DisplayInfo getDisplayInfoInternal(int displayId, int callingUid) {
synchronized (mSyncRoot) {
- int callingPid = Binder.getCallingPid();
+ LogicalDisplay display = mLogicalDisplays.get(displayId);
+ if (display != null) {
+ DisplayInfo info = display.getDisplayInfoLocked();
+ if (info.hasAccess(callingUid)) {
+ return info;
+ }
+ }
+ return null;
+ }
+ }
+
+ private int[] getDisplayIdsInternal(int callingUid) {
+ synchronized (mSyncRoot) {
+ final int count = mLogicalDisplays.size();
+ int[] displayIds = new int[count];
+ int n = 0;
+ for (int i = 0; i < count; i++) {
+ LogicalDisplay display = mLogicalDisplays.valueAt(i);
+ DisplayInfo info = display.getDisplayInfoLocked();
+ if (info.hasAccess(callingUid)) {
+ displayIds[n++] = mLogicalDisplays.keyAt(i);
+ }
+ }
+ if (n != count) {
+ displayIds = Arrays.copyOfRange(displayIds, 0, n);
+ }
+ return displayIds;
+ }
+ }
+
+ private void registerCallbackInternal(IDisplayManagerCallback callback, int callingPid) {
+ synchronized (mSyncRoot) {
if (mCallbacks.get(callingPid) != null) {
throw new SecurityException("The calling process has already "
+ "registered an IDisplayManagerCallback.");
@@ -469,24 +393,14 @@
}
}
- @Override // Binder call
- public void startWifiDisplayScan() {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
- "Permission required to start wifi display scans");
-
- final int callingPid = Binder.getCallingPid();
- final long token = Binder.clearCallingIdentity();
- try {
- synchronized (mSyncRoot) {
- CallbackRecord record = mCallbacks.get(callingPid);
- if (record == null) {
- throw new IllegalStateException("The calling process has not "
- + "registered an IDisplayManagerCallback.");
- }
- startWifiDisplayScanLocked(record);
+ private void startWifiDisplayScanInternal(int callingPid) {
+ synchronized (mSyncRoot) {
+ CallbackRecord record = mCallbacks.get(callingPid);
+ if (record == null) {
+ throw new IllegalStateException("The calling process has not "
+ + "registered an IDisplayManagerCallback.");
}
- } finally {
- Binder.restoreCallingIdentity(token);
+ startWifiDisplayScanLocked(record);
}
}
@@ -501,24 +415,14 @@
}
}
- @Override // Binder call
- public void stopWifiDisplayScan() {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
- "Permission required to stop wifi display scans");
-
- final int callingPid = Binder.getCallingPid();
- final long token = Binder.clearCallingIdentity();
- try {
- synchronized (mSyncRoot) {
- CallbackRecord record = mCallbacks.get(callingPid);
- if (record == null) {
- throw new IllegalStateException("The calling process has not "
- + "registered an IDisplayManagerCallback.");
- }
- stopWifiDisplayScanLocked(record);
+ private void stopWifiDisplayScanInternal(int callingPid) {
+ synchronized (mSyncRoot) {
+ CallbackRecord record = mCallbacks.get(callingPid);
+ if (record == null) {
+ throw new IllegalStateException("The calling process has not "
+ + "registered an IDisplayManagerCallback.");
}
- } finally {
- Binder.restoreCallingIdentity(token);
+ stopWifiDisplayScanLocked(record);
}
}
@@ -537,255 +441,113 @@
}
}
- @Override // Binder call
- public void connectWifiDisplay(String address) {
- if (address == null) {
- throw new IllegalArgumentException("address must not be null");
- }
- mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
- "Permission required to connect to a wifi display");
-
- final long token = Binder.clearCallingIdentity();
- try {
- synchronized (mSyncRoot) {
- if (mWifiDisplayAdapter != null) {
- mWifiDisplayAdapter.requestConnectLocked(address);
- }
+ private void connectWifiDisplayInternal(String address) {
+ synchronized (mSyncRoot) {
+ if (mWifiDisplayAdapter != null) {
+ mWifiDisplayAdapter.requestConnectLocked(address);
}
- } finally {
- Binder.restoreCallingIdentity(token);
}
}
- @Override
- public void pauseWifiDisplay() {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
- "Permission required to pause a wifi display session");
-
- final long token = Binder.clearCallingIdentity();
- try {
- synchronized (mSyncRoot) {
- if (mWifiDisplayAdapter != null) {
- mWifiDisplayAdapter.requestPauseLocked();
- }
+ private void pauseWifiDisplayInternal() {
+ synchronized (mSyncRoot) {
+ if (mWifiDisplayAdapter != null) {
+ mWifiDisplayAdapter.requestPauseLocked();
}
- } finally {
- Binder.restoreCallingIdentity(token);
}
}
- @Override
- public void resumeWifiDisplay() {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
- "Permission required to resume a wifi display session");
-
- final long token = Binder.clearCallingIdentity();
- try {
- synchronized (mSyncRoot) {
- if (mWifiDisplayAdapter != null) {
- mWifiDisplayAdapter.requestResumeLocked();
- }
+ private void resumeWifiDisplayInternal() {
+ synchronized (mSyncRoot) {
+ if (mWifiDisplayAdapter != null) {
+ mWifiDisplayAdapter.requestResumeLocked();
}
- } finally {
- Binder.restoreCallingIdentity(token);
}
}
- @Override // Binder call
- public void disconnectWifiDisplay() {
- // This request does not require special permissions.
- // Any app can request disconnection from the currently active wifi display.
- // This exception should no longer be needed once wifi display control moves
- // to the media router service.
-
- final long token = Binder.clearCallingIdentity();
- try {
- synchronized (mSyncRoot) {
- if (mWifiDisplayAdapter != null) {
- mWifiDisplayAdapter.requestDisconnectLocked();
- }
+ private void disconnectWifiDisplayInternal() {
+ synchronized (mSyncRoot) {
+ if (mWifiDisplayAdapter != null) {
+ mWifiDisplayAdapter.requestDisconnectLocked();
}
- } finally {
- Binder.restoreCallingIdentity(token);
}
}
- @Override // Binder call
- public void renameWifiDisplay(String address, String alias) {
- if (address == null) {
- throw new IllegalArgumentException("address must not be null");
- }
- mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
- "Permission required to rename to a wifi display");
-
- final long token = Binder.clearCallingIdentity();
- try {
- synchronized (mSyncRoot) {
- if (mWifiDisplayAdapter != null) {
- mWifiDisplayAdapter.requestRenameLocked(address, alias);
- }
+ private void renameWifiDisplayInternal(String address, String alias) {
+ synchronized (mSyncRoot) {
+ if (mWifiDisplayAdapter != null) {
+ mWifiDisplayAdapter.requestRenameLocked(address, alias);
}
- } finally {
- Binder.restoreCallingIdentity(token);
}
}
- @Override // Binder call
- public void forgetWifiDisplay(String address) {
- if (address == null) {
- throw new IllegalArgumentException("address must not be null");
- }
- mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
- "Permission required to forget to a wifi display");
-
- final long token = Binder.clearCallingIdentity();
- try {
- synchronized (mSyncRoot) {
- if (mWifiDisplayAdapter != null) {
- mWifiDisplayAdapter.requestForgetLocked(address);
- }
+ private void forgetWifiDisplayInternal(String address) {
+ synchronized (mSyncRoot) {
+ if (mWifiDisplayAdapter != null) {
+ mWifiDisplayAdapter.requestForgetLocked(address);
}
- } finally {
- Binder.restoreCallingIdentity(token);
}
}
- @Override // Binder call
- public WifiDisplayStatus getWifiDisplayStatus() {
- // This request does not require special permissions.
- // Any app can get information about available wifi displays.
-
- final long token = Binder.clearCallingIdentity();
- try {
- synchronized (mSyncRoot) {
- if (mWifiDisplayAdapter != null) {
- return mWifiDisplayAdapter.getWifiDisplayStatusLocked();
- }
- return new WifiDisplayStatus();
+ private WifiDisplayStatus getWifiDisplayStatusInternal() {
+ synchronized (mSyncRoot) {
+ if (mWifiDisplayAdapter != null) {
+ return mWifiDisplayAdapter.getWifiDisplayStatusLocked();
}
- } finally {
- Binder.restoreCallingIdentity(token);
+ return new WifiDisplayStatus();
}
}
- @Override // Binder call
- public int createVirtualDisplay(IBinder appToken, String packageName,
+ private int createVirtualDisplayInternal(IBinder appToken, int callingUid, String packageName,
String name, int width, int height, int densityDpi, Surface surface, int flags) {
- final int callingUid = Binder.getCallingUid();
- if (!validatePackageName(callingUid, packageName)) {
- throw new SecurityException("packageName must match the calling uid");
- }
- if (appToken == null) {
- throw new IllegalArgumentException("appToken must not be null");
- }
- if (TextUtils.isEmpty(name)) {
- throw new IllegalArgumentException("name must be non-null and non-empty");
- }
- if (width <= 0 || height <= 0 || densityDpi <= 0) {
- throw new IllegalArgumentException("width, height, and densityDpi must be "
- + "greater than 0");
- }
- if (surface == null) {
- throw new IllegalArgumentException("surface must not be null");
- }
- if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) {
- if (mContext.checkCallingPermission(android.Manifest.permission.CAPTURE_VIDEO_OUTPUT)
- != PackageManager.PERMISSION_GRANTED
- && mContext.checkCallingPermission(
- android.Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Requires CAPTURE_VIDEO_OUTPUT or "
- + "CAPTURE_SECURE_VIDEO_OUTPUT permission to create a "
- + "public virtual display.");
+ synchronized (mSyncRoot) {
+ if (mVirtualDisplayAdapter == null) {
+ Slog.w(TAG, "Rejecting request to create private virtual display "
+ + "because the virtual display adapter is not available.");
+ return -1;
}
- }
- if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE) != 0) {
- if (mContext.checkCallingPermission(
- android.Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Requires CAPTURE_SECURE_VIDEO_OUTPUT "
- + "to create a secure virtual display.");
+
+ DisplayDevice device = mVirtualDisplayAdapter.createVirtualDisplayLocked(
+ appToken, callingUid, packageName, name, width, height, densityDpi,
+ surface, flags);
+ if (device == null) {
+ return -1;
}
- }
- final long token = Binder.clearCallingIdentity();
- try {
- synchronized (mSyncRoot) {
- if (mVirtualDisplayAdapter == null) {
- Slog.w(TAG, "Rejecting request to create private virtual display "
- + "because the virtual display adapter is not available.");
- return -1;
- }
-
- DisplayDevice device = mVirtualDisplayAdapter.createVirtualDisplayLocked(
- appToken, callingUid, packageName, name, width, height, densityDpi,
- surface, flags);
- if (device == null) {
- return -1;
- }
-
- handleDisplayDeviceAddedLocked(device);
- LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
- if (display != null) {
- return display.getDisplayIdLocked();
- }
-
- // Something weird happened and the logical display was not created.
- Slog.w(TAG, "Rejecting request to create virtual display "
- + "because the logical display was not created.");
- mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken);
- handleDisplayDeviceRemovedLocked(device);
+ handleDisplayDeviceAddedLocked(device);
+ LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
+ if (display != null) {
+ return display.getDisplayIdLocked();
}
- } finally {
- Binder.restoreCallingIdentity(token);
+
+ // Something weird happened and the logical display was not created.
+ Slog.w(TAG, "Rejecting request to create virtual display "
+ + "because the logical display was not created.");
+ mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken);
+ handleDisplayDeviceRemovedLocked(device);
}
return -1;
}
- @Override // Binder call
- public void releaseVirtualDisplay(IBinder appToken) {
- final long token = Binder.clearCallingIdentity();
- try {
- synchronized (mSyncRoot) {
- if (mVirtualDisplayAdapter == null) {
- return;
- }
-
- DisplayDevice device =
- mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken);
- if (device != null) {
- handleDisplayDeviceRemovedLocked(device);
- }
+ private void releaseVirtualDisplayInternal(IBinder appToken) {
+ synchronized (mSyncRoot) {
+ if (mVirtualDisplayAdapter == null) {
+ return;
}
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
- private boolean validatePackageName(int uid, String packageName) {
- if (packageName != null) {
- String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid);
- if (packageNames != null) {
- for (String n : packageNames) {
- if (n.equals(packageName)) {
- return true;
- }
- }
+ DisplayDevice device =
+ mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken);
+ if (device != null) {
+ handleDisplayDeviceRemovedLocked(device);
}
}
- return false;
}
private void registerDefaultDisplayAdapter() {
// Register default display adapter.
synchronized (mSyncRoot) {
- if (mHeadless) {
- registerDisplayAdapterLocked(new HeadlessDisplayAdapter(
- mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
- } else {
- registerDisplayAdapterLocked(new LocalDisplayAdapter(
- mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
- }
+ registerDisplayAdapterLocked(new LocalDisplayAdapter(
+ mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
}
}
@@ -1002,26 +764,13 @@
}
// Tell the input system about these new viewports.
- if (mInputManagerFuncs != null) {
+ if (mInputManagerInternal != null) {
mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT);
}
}
- /**
- * Tells the display manager whether there is interesting unique content on the
- * specified logical display. This is used to control automatic mirroring.
- * <p>
- * If the display has unique content, then the display manager arranges for it
- * to be presented on a physical display if appropriate. Otherwise, the display manager
- * may choose to make the physical display mirror some other logical display.
- * </p>
- *
- * @param displayId The logical display id to update.
- * @param hasContent True if the logical display has content.
- * @param inTraversal True if called from WindowManagerService during a window traversal prior
- * to call to performTraversalInTransactionFromWindowManager.
- */
- public void setDisplayHasContent(int displayId, boolean hasContent, boolean inTraversal) {
+ private void setDisplayHasContentInternal(int displayId, boolean hasContent,
+ boolean inTraversal) {
synchronized (mSyncRoot) {
LogicalDisplay display = mLogicalDisplays.get(displayId);
if (display != null && display.hasContentLocked() != hasContent) {
@@ -1042,13 +791,13 @@
}
private void configureDisplayInTransactionLocked(DisplayDevice device) {
- DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
- boolean isPrivate = (info.flags & DisplayDeviceInfo.FLAG_PRIVATE) != 0;
+ final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
+ final boolean ownContent = (info.flags & DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY) != 0;
// Find the logical display that the display device is showing.
- // Private displays never mirror other displays.
+ // Certain displays only ever show their own content.
LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
- if (!isPrivate) {
+ if (!ownContent) {
if (display != null && !display.hasContentLocked()) {
// If the display does not have any content of its own, then
// automatically mirror the default logical display contents.
@@ -1107,7 +856,7 @@
// Requests that performTraversalsInTransactionFromWindowManager be called at a
// later time to apply changes to surfaces and displays.
private void scheduleTraversalLocked(boolean inTraversal) {
- if (!mPendingTraversal && mWindowManagerFuncs != null) {
+ if (!mPendingTraversal && mWindowManagerInternal != null) {
mPendingTraversal = true;
if (!inTraversal) {
mHandler.sendEmptyMessage(MSG_REQUEST_TRAVERSAL);
@@ -1140,20 +889,10 @@
mTempCallbacks.clear();
}
- @Override // Binder call
- public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
- if (mContext == null
- || mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump DisplayManager from from pid="
- + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
- return;
- }
-
+ private void dumpInternal(PrintWriter pw) {
pw.println("DISPLAY MANAGER (dumpsys display)");
synchronized (mSyncRoot) {
- pw.println(" mHeadless=" + mHeadless);
pw.println(" mOnlyCode=" + mOnlyCore);
pw.println(" mSafeMode=" + mSafeMode);
pw.println(" mPendingTraversal=" + mPendingTraversal);
@@ -1212,30 +951,6 @@
public static final class SyncRoot {
}
- /**
- * Private interface to the window manager.
- */
- public interface WindowManagerFuncs {
- /**
- * Request that the window manager call
- * {@link #performTraversalInTransactionFromWindowManager} within a surface
- * transaction at a later time.
- */
- void requestTraversal();
- }
-
- /**
- * Private interface to the input manager.
- */
- public interface InputManagerFuncs {
- /**
- * Sets information about the displays as needed by the input system.
- * The input system should copy this information if required.
- */
- void setDisplayViewports(DisplayViewport defaultViewport,
- DisplayViewport externalTouchViewport);
- }
-
private final class DisplayManagerHandler extends Handler {
public DisplayManagerHandler(Looper looper) {
super(looper, null, true /*async*/);
@@ -1257,7 +972,7 @@
break;
case MSG_REQUEST_TRAVERSAL:
- mWindowManagerFuncs.requestTraversal();
+ mWindowManagerInternal.requestTraversalFromDisplayManager();
break;
case MSG_UPDATE_VIEWPORT: {
@@ -1265,7 +980,7 @@
mTempDefaultViewport.copyFrom(mDefaultViewport);
mTempExternalTouchViewport.copyFrom(mExternalTouchViewport);
}
- mInputManagerFuncs.setDisplayViewports(
+ mInputManagerInternal.setDisplayViewports(
mTempDefaultViewport, mTempExternalTouchViewport);
break;
}
@@ -1328,4 +1043,325 @@
}
}
}
+
+ private final class BinderService extends IDisplayManager.Stub {
+ /**
+ * Returns information about the specified logical display.
+ *
+ * @param displayId The logical display id.
+ * @return The logical display info, or null if the display does not exist. The
+ * returned object must be treated as immutable.
+ */
+ @Override // Binder call
+ public DisplayInfo getDisplayInfo(int displayId) {
+ final int callingUid = Binder.getCallingUid();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ return getDisplayInfoInternal(displayId, callingUid);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Returns the list of all display ids.
+ */
+ @Override // Binder call
+ public int[] getDisplayIds() {
+ final int callingUid = Binder.getCallingUid();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ return getDisplayIdsInternal(callingUid);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override // Binder call
+ public void registerCallback(IDisplayManagerCallback callback) {
+ if (callback == null) {
+ throw new IllegalArgumentException("listener must not be null");
+ }
+
+ final int callingPid = Binder.getCallingPid();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ registerCallbackInternal(callback, callingPid);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override // Binder call
+ public void startWifiDisplayScan() {
+ mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
+ "Permission required to start wifi display scans");
+
+ final int callingPid = Binder.getCallingPid();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ startWifiDisplayScanInternal(callingPid);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override // Binder call
+ public void stopWifiDisplayScan() {
+ mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
+ "Permission required to stop wifi display scans");
+
+ final int callingPid = Binder.getCallingPid();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ stopWifiDisplayScanInternal(callingPid);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override // Binder call
+ public void connectWifiDisplay(String address) {
+ if (address == null) {
+ throw new IllegalArgumentException("address must not be null");
+ }
+ mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
+ "Permission required to connect to a wifi display");
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ connectWifiDisplayInternal(address);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override // Binder call
+ public void disconnectWifiDisplay() {
+ // This request does not require special permissions.
+ // Any app can request disconnection from the currently active wifi display.
+ // This exception should no longer be needed once wifi display control moves
+ // to the media router service.
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ disconnectWifiDisplayInternal();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override // Binder call
+ public void renameWifiDisplay(String address, String alias) {
+ if (address == null) {
+ throw new IllegalArgumentException("address must not be null");
+ }
+ mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
+ "Permission required to rename to a wifi display");
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ renameWifiDisplayInternal(address, alias);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override // Binder call
+ public void forgetWifiDisplay(String address) {
+ if (address == null) {
+ throw new IllegalArgumentException("address must not be null");
+ }
+ mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
+ "Permission required to forget to a wifi display");
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ forgetWifiDisplayInternal(address);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override // Binder call
+ public void pauseWifiDisplay() {
+ mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
+ "Permission required to pause a wifi display session");
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ pauseWifiDisplayInternal();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override // Binder call
+ public void resumeWifiDisplay() {
+ mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
+ "Permission required to resume a wifi display session");
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ resumeWifiDisplayInternal();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override // Binder call
+ public WifiDisplayStatus getWifiDisplayStatus() {
+ // This request does not require special permissions.
+ // Any app can get information about available wifi displays.
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ return getWifiDisplayStatusInternal();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override // Binder call
+ public int createVirtualDisplay(IBinder appToken, String packageName,
+ String name, int width, int height, int densityDpi, Surface surface, int flags) {
+ final int callingUid = Binder.getCallingUid();
+ if (!validatePackageName(callingUid, packageName)) {
+ throw new SecurityException("packageName must match the calling uid");
+ }
+ if (appToken == null) {
+ throw new IllegalArgumentException("appToken must not be null");
+ }
+ if (TextUtils.isEmpty(name)) {
+ throw new IllegalArgumentException("name must be non-null and non-empty");
+ }
+ if (width <= 0 || height <= 0 || densityDpi <= 0) {
+ throw new IllegalArgumentException("width, height, and densityDpi must be "
+ + "greater than 0");
+ }
+ if (surface == null) {
+ throw new IllegalArgumentException("surface must not be null");
+ }
+ if (callingUid != Process.SYSTEM_UID &&
+ (flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) {
+ if (mContext.checkCallingPermission(android.Manifest.permission.CAPTURE_VIDEO_OUTPUT)
+ != PackageManager.PERMISSION_GRANTED
+ && mContext.checkCallingPermission(
+ android.Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Requires CAPTURE_VIDEO_OUTPUT or "
+ + "CAPTURE_SECURE_VIDEO_OUTPUT permission to create a "
+ + "public virtual display.");
+ }
+ }
+ if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE) != 0) {
+ if (mContext.checkCallingPermission(
+ android.Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Requires CAPTURE_SECURE_VIDEO_OUTPUT "
+ + "to create a secure virtual display.");
+ }
+ }
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ return createVirtualDisplayInternal(appToken, callingUid, packageName,
+ name, width, height, densityDpi, surface, flags);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override // Binder call
+ public void releaseVirtualDisplay(IBinder appToken) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ releaseVirtualDisplayInternal(appToken);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override // Binder call
+ public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
+ if (mContext == null
+ || mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
+ != PackageManager.PERMISSION_GRANTED) {
+ pw.println("Permission Denial: can't dump DisplayManager from from pid="
+ + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
+ return;
+ }
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ dumpInternal(pw);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ private boolean validatePackageName(int uid, String packageName) {
+ if (packageName != null) {
+ String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid);
+ if (packageNames != null) {
+ for (String n : packageNames) {
+ if (n.equals(packageName)) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+ }
+
+ private final class LocalService extends DisplayManagerInternal {
+ @Override
+ public void blankAllDisplaysFromPowerManager() {
+ blankAllDisplaysFromPowerManagerInternal();
+ }
+
+ @Override
+ public void unblankAllDisplaysFromPowerManager() {
+ unblankAllDisplaysFromPowerManagerInternal();
+ }
+
+ @Override
+ public DisplayInfo getDisplayInfo(int displayId) {
+ return getDisplayInfoInternal(displayId, Process.myUid());
+ }
+
+ @Override
+ public void registerDisplayTransactionListener(DisplayTransactionListener listener) {
+ if (listener == null) {
+ throw new IllegalArgumentException("listener must not be null");
+ }
+
+ registerDisplayTransactionListenerInternal(listener);
+ }
+
+ @Override
+ public void unregisterDisplayTransactionListener(DisplayTransactionListener listener) {
+ if (listener == null) {
+ throw new IllegalArgumentException("listener must not be null");
+ }
+
+ unregisterDisplayTransactionListenerInternal(listener);
+ }
+
+ @Override
+ public void setDisplayInfoOverrideFromWindowManager(int displayId, DisplayInfo info) {
+ setDisplayInfoOverrideFromWindowManagerInternal(displayId, info);
+ }
+
+ @Override
+ public void performTraversalInTransactionFromWindowManager() {
+ performTraversalInTransactionFromWindowManagerInternal();
+ }
+
+ @Override
+ public void setDisplayHasContent(int displayId, boolean hasContent, boolean inTraversal) {
+ setDisplayHasContentInternal(displayId, hasContent, inTraversal);
+ }
+ }
}
diff --git a/services/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
similarity index 100%
rename from services/java/com/android/server/display/LocalDisplayAdapter.java
rename to services/core/java/com/android/server/display/LocalDisplayAdapter.java
diff --git a/services/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
similarity index 100%
rename from services/java/com/android/server/display/LogicalDisplay.java
rename to services/core/java/com/android/server/display/LogicalDisplay.java
diff --git a/services/java/com/android/server/display/OverlayDisplayAdapter.java b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
similarity index 100%
rename from services/java/com/android/server/display/OverlayDisplayAdapter.java
rename to services/core/java/com/android/server/display/OverlayDisplayAdapter.java
diff --git a/services/java/com/android/server/display/OverlayDisplayWindow.java b/services/core/java/com/android/server/display/OverlayDisplayWindow.java
similarity index 100%
rename from services/java/com/android/server/display/OverlayDisplayWindow.java
rename to services/core/java/com/android/server/display/OverlayDisplayWindow.java
diff --git a/services/java/com/android/server/display/PersistentDataStore.java b/services/core/java/com/android/server/display/PersistentDataStore.java
similarity index 100%
rename from services/java/com/android/server/display/PersistentDataStore.java
rename to services/core/java/com/android/server/display/PersistentDataStore.java
diff --git a/services/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
similarity index 95%
rename from services/java/com/android/server/display/VirtualDisplayAdapter.java
rename to services/core/java/com/android/server/display/VirtualDisplayAdapter.java
index 46d473c..95ca0d2 100644
--- a/services/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -157,8 +157,11 @@
mInfo.yDpi = mDensityDpi;
mInfo.flags = 0;
if ((mFlags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC) == 0) {
- mInfo.flags |= DisplayDeviceInfo.FLAG_PRIVATE |
- DisplayDeviceInfo.FLAG_NEVER_BLANK;
+ mInfo.flags |= DisplayDeviceInfo.FLAG_PRIVATE
+ | DisplayDeviceInfo.FLAG_NEVER_BLANK
+ | DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY;
+ } else if ((mFlags & DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY) != 0) {
+ mInfo.flags |= DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY;
}
if ((mFlags & DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE) != 0) {
mInfo.flags |= DisplayDeviceInfo.FLAG_SECURE;
diff --git a/services/java/com/android/server/display/WifiDisplayAdapter.java b/services/core/java/com/android/server/display/WifiDisplayAdapter.java
similarity index 100%
rename from services/java/com/android/server/display/WifiDisplayAdapter.java
rename to services/core/java/com/android/server/display/WifiDisplayAdapter.java
diff --git a/services/java/com/android/server/display/WifiDisplayController.java b/services/core/java/com/android/server/display/WifiDisplayController.java
similarity index 100%
rename from services/java/com/android/server/display/WifiDisplayController.java
rename to services/core/java/com/android/server/display/WifiDisplayController.java
diff --git a/services/java/com/android/server/dreams/DreamController.java b/services/core/java/com/android/server/dreams/DreamController.java
similarity index 100%
rename from services/java/com/android/server/dreams/DreamController.java
rename to services/core/java/com/android/server/dreams/DreamController.java
diff --git a/services/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
similarity index 98%
rename from services/java/com/android/server/dreams/DreamManagerService.java
rename to services/core/java/com/android/server/dreams/DreamManagerService.java
index b6e7781..f5acc4c 100644
--- a/services/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -17,6 +17,7 @@
package com.android.server.dreams;
import com.android.internal.util.DumpUtils;
+import com.android.server.FgThread;
import android.app.ActivityManager;
import android.content.BroadcastReceiver;
@@ -65,9 +66,9 @@
private int mCurrentDreamUserId;
private boolean mCurrentDreamIsTest;
- public DreamManagerService(Context context, Handler mainHandler) {
+ public DreamManagerService(Context context) {
mContext = context;
- mHandler = new DreamHandler(mainHandler.getLooper());
+ mHandler = new DreamHandler(FgThread.get().getLooper());
mController = new DreamController(context, mHandler, mControllerListener);
mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
diff --git a/services/java/com/android/server/firewall/AndFilter.java b/services/core/java/com/android/server/firewall/AndFilter.java
similarity index 100%
rename from services/java/com/android/server/firewall/AndFilter.java
rename to services/core/java/com/android/server/firewall/AndFilter.java
diff --git a/services/java/com/android/server/firewall/CategoryFilter.java b/services/core/java/com/android/server/firewall/CategoryFilter.java
similarity index 100%
rename from services/java/com/android/server/firewall/CategoryFilter.java
rename to services/core/java/com/android/server/firewall/CategoryFilter.java
diff --git a/services/java/com/android/server/firewall/Filter.java b/services/core/java/com/android/server/firewall/Filter.java
similarity index 100%
rename from services/java/com/android/server/firewall/Filter.java
rename to services/core/java/com/android/server/firewall/Filter.java
diff --git a/services/java/com/android/server/firewall/FilterFactory.java b/services/core/java/com/android/server/firewall/FilterFactory.java
similarity index 100%
rename from services/java/com/android/server/firewall/FilterFactory.java
rename to services/core/java/com/android/server/firewall/FilterFactory.java
diff --git a/services/java/com/android/server/firewall/FilterList.java b/services/core/java/com/android/server/firewall/FilterList.java
similarity index 100%
rename from services/java/com/android/server/firewall/FilterList.java
rename to services/core/java/com/android/server/firewall/FilterList.java
diff --git a/services/java/com/android/server/firewall/IntentFirewall.java b/services/core/java/com/android/server/firewall/IntentFirewall.java
similarity index 98%
rename from services/java/com/android/server/firewall/IntentFirewall.java
rename to services/core/java/com/android/server/firewall/IntentFirewall.java
index aaa0b58..88a2207 100644
--- a/services/java/com/android/server/firewall/IntentFirewall.java
+++ b/services/core/java/com/android/server/firewall/IntentFirewall.java
@@ -26,6 +26,7 @@
import android.os.Environment;
import android.os.FileObserver;
import android.os.Handler;
+import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.util.ArrayMap;
@@ -106,8 +107,9 @@
}
}
- public IntentFirewall(AMSInterface ams) {
+ public IntentFirewall(AMSInterface ams, Handler handler) {
mAms = ams;
+ mHandler = new FirewallHandler(handler.getLooper());
File rulesDir = getRulesDir();
rulesDir.mkdirs();
@@ -531,7 +533,13 @@
new ArrayMap<ComponentName, Rule[]>(0);
}
- final Handler mHandler = new Handler() {
+ final FirewallHandler mHandler;
+
+ private final class FirewallHandler extends Handler {
+ public FirewallHandler(Looper looper) {
+ super(looper, null, true);
+ }
+
@Override
public void handleMessage(Message msg) {
readRulesDir(getRulesDir());
diff --git a/services/java/com/android/server/firewall/NotFilter.java b/services/core/java/com/android/server/firewall/NotFilter.java
similarity index 100%
rename from services/java/com/android/server/firewall/NotFilter.java
rename to services/core/java/com/android/server/firewall/NotFilter.java
diff --git a/services/java/com/android/server/firewall/OrFilter.java b/services/core/java/com/android/server/firewall/OrFilter.java
similarity index 100%
rename from services/java/com/android/server/firewall/OrFilter.java
rename to services/core/java/com/android/server/firewall/OrFilter.java
diff --git a/services/java/com/android/server/firewall/PortFilter.java b/services/core/java/com/android/server/firewall/PortFilter.java
similarity index 100%
rename from services/java/com/android/server/firewall/PortFilter.java
rename to services/core/java/com/android/server/firewall/PortFilter.java
diff --git a/services/java/com/android/server/firewall/SenderFilter.java b/services/core/java/com/android/server/firewall/SenderFilter.java
similarity index 100%
rename from services/java/com/android/server/firewall/SenderFilter.java
rename to services/core/java/com/android/server/firewall/SenderFilter.java
diff --git a/services/java/com/android/server/firewall/SenderPermissionFilter.java b/services/core/java/com/android/server/firewall/SenderPermissionFilter.java
similarity index 100%
rename from services/java/com/android/server/firewall/SenderPermissionFilter.java
rename to services/core/java/com/android/server/firewall/SenderPermissionFilter.java
diff --git a/services/java/com/android/server/firewall/StringFilter.java b/services/core/java/com/android/server/firewall/StringFilter.java
similarity index 100%
rename from services/java/com/android/server/firewall/StringFilter.java
rename to services/core/java/com/android/server/firewall/StringFilter.java
diff --git a/services/java/com/android/server/input/InputApplicationHandle.java b/services/core/java/com/android/server/input/InputApplicationHandle.java
similarity index 100%
rename from services/java/com/android/server/input/InputApplicationHandle.java
rename to services/core/java/com/android/server/input/InputApplicationHandle.java
diff --git a/services/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
similarity index 98%
rename from services/java/com/android/server/input/InputManagerService.java
rename to services/core/java/com/android/server/input/InputManagerService.java
index 9178664..fa18149 100644
--- a/services/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -18,9 +18,9 @@
import com.android.internal.R;
import com.android.internal.util.XmlUtils;
+import com.android.server.DisplayThread;
+import com.android.server.LocalServices;
import com.android.server.Watchdog;
-import com.android.server.display.DisplayManagerService;
-import com.android.server.display.DisplayViewport;
import org.xmlpull.v1.XmlPullParser;
@@ -44,9 +44,11 @@
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.database.ContentObserver;
+import android.hardware.display.DisplayViewport;
import android.hardware.input.IInputDevicesChangedListener;
import android.hardware.input.IInputManager;
import android.hardware.input.InputManager;
+import android.hardware.input.InputManagerInternal;
import android.hardware.input.KeyboardLayout;
import android.os.Binder;
import android.os.Bundle;
@@ -94,7 +96,7 @@
* Wraps the C++ InputManager and provides its callbacks.
*/
public class InputManagerService extends IInputManager.Stub
- implements Watchdog.Monitor, DisplayManagerService.InputManagerFuncs {
+ implements Watchdog.Monitor {
static final String TAG = "InputManager";
static final boolean DEBUG = false;
@@ -241,15 +243,17 @@
/** Whether to use the dev/input/event or uevent subsystem for the audio jack. */
final boolean mUseDevInputEventForAudioJack;
- public InputManagerService(Context context, Handler handler) {
+ public InputManagerService(Context context) {
this.mContext = context;
- this.mHandler = new InputManagerHandler(handler.getLooper());
+ this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
mUseDevInputEventForAudioJack =
context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
+ mUseDevInputEventForAudioJack);
mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
+
+ LocalServices.addService(InputManagerInternal.class, new LocalService());
}
public void setWindowManagerCallbacks(WindowManagerCallbacks callbacks) {
@@ -329,8 +333,7 @@
nativeReloadDeviceAliases(mPtr);
}
- @Override
- public void setDisplayViewports(DisplayViewport defaultViewport,
+ private void setDisplayViewportsInternal(DisplayViewport defaultViewport,
DisplayViewport externalTouchViewport) {
if (defaultViewport.valid) {
setDisplayViewport(false, defaultViewport);
@@ -1639,4 +1642,12 @@
onVibratorTokenDied(this);
}
}
+
+ private final class LocalService extends InputManagerInternal {
+ @Override
+ public void setDisplayViewports(
+ DisplayViewport defaultViewport, DisplayViewport externalTouchViewport) {
+ setDisplayViewportsInternal(defaultViewport, externalTouchViewport);
+ }
+ }
}
diff --git a/services/java/com/android/server/input/InputWindowHandle.java b/services/core/java/com/android/server/input/InputWindowHandle.java
similarity index 100%
rename from services/java/com/android/server/input/InputWindowHandle.java
rename to services/core/java/com/android/server/input/InputWindowHandle.java
diff --git a/services/java/com/android/server/input/PersistentDataStore.java b/services/core/java/com/android/server/input/PersistentDataStore.java
similarity index 100%
rename from services/java/com/android/server/input/PersistentDataStore.java
rename to services/core/java/com/android/server/input/PersistentDataStore.java
diff --git a/services/core/java/com/android/server/lights/Light.java b/services/core/java/com/android/server/lights/Light.java
new file mode 100644
index 0000000..b496b4c6
--- /dev/null
+++ b/services/core/java/com/android/server/lights/Light.java
@@ -0,0 +1,41 @@
+/*
+ * 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.server.lights;
+
+public abstract class Light {
+ public static final int LIGHT_FLASH_NONE = 0;
+ public static final int LIGHT_FLASH_TIMED = 1;
+ public static final int LIGHT_FLASH_HARDWARE = 2;
+
+ /**
+ * Light brightness is managed by a user setting.
+ */
+ public static final int BRIGHTNESS_MODE_USER = 0;
+
+ /**
+ * Light brightness is managed by a light sensor.
+ */
+ public static final int BRIGHTNESS_MODE_SENSOR = 1;
+
+ public abstract void setBrightness(int brightness);
+ public abstract void setBrightness(int brightness, int brightnessMode);
+ public abstract void setColor(int color);
+ public abstract void setFlashing(int color, int mode, int onMS, int offMS);
+ public abstract void pulse();
+ public abstract void pulse(int color, int onMS);
+ public abstract void turnOff();
+}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/lights/LightsManager.java b/services/core/java/com/android/server/lights/LightsManager.java
new file mode 100644
index 0000000..2f20509
--- /dev/null
+++ b/services/core/java/com/android/server/lights/LightsManager.java
@@ -0,0 +1,31 @@
+/*
+ * 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.server.lights;
+
+public abstract class LightsManager {
+ public static final int LIGHT_ID_BACKLIGHT = 0;
+ public static final int LIGHT_ID_KEYBOARD = 1;
+ public static final int LIGHT_ID_BUTTONS = 2;
+ public static final int LIGHT_ID_BATTERY = 3;
+ public static final int LIGHT_ID_NOTIFICATIONS = 4;
+ public static final int LIGHT_ID_ATTENTION = 5;
+ public static final int LIGHT_ID_BLUETOOTH = 6;
+ public static final int LIGHT_ID_WIFI = 7;
+ public static final int LIGHT_ID_COUNT = 8;
+
+ public abstract Light getLight(int id);
+}
diff --git a/services/java/com/android/server/LightsService.java b/services/core/java/com/android/server/lights/LightsService.java
similarity index 74%
rename from services/java/com/android/server/LightsService.java
rename to services/core/java/com/android/server/lights/LightsService.java
index a1d655b..62dc090 100644
--- a/services/java/com/android/server/LightsService.java
+++ b/services/core/java/com/android/server/lights/LightsService.java
@@ -14,59 +14,38 @@
* limitations under the License.
*/
-package com.android.server;
+package com.android.server.lights;
+
+import com.android.server.SystemService;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Handler;
import android.os.IHardwareService;
-import android.os.ServiceManager;
import android.os.Message;
import android.util.Slog;
import java.io.FileInputStream;
import java.io.FileOutputStream;
-public class LightsService {
- private static final String TAG = "LightsService";
- private static final boolean DEBUG = false;
+public class LightsService extends SystemService {
+ static final String TAG = "LightsService";
+ static final boolean DEBUG = false;
- public static final int LIGHT_ID_BACKLIGHT = 0;
- public static final int LIGHT_ID_KEYBOARD = 1;
- public static final int LIGHT_ID_BUTTONS = 2;
- public static final int LIGHT_ID_BATTERY = 3;
- public static final int LIGHT_ID_NOTIFICATIONS = 4;
- public static final int LIGHT_ID_ATTENTION = 5;
- public static final int LIGHT_ID_BLUETOOTH = 6;
- public static final int LIGHT_ID_WIFI = 7;
- public static final int LIGHT_ID_COUNT = 8;
+ final LightImpl mLights[] = new LightImpl[LightsManager.LIGHT_ID_COUNT];
- public static final int LIGHT_FLASH_NONE = 0;
- public static final int LIGHT_FLASH_TIMED = 1;
- public static final int LIGHT_FLASH_HARDWARE = 2;
+ private final class LightImpl extends Light {
- /**
- * Light brightness is managed by a user setting.
- */
- public static final int BRIGHTNESS_MODE_USER = 0;
-
- /**
- * Light brightness is managed by a light sensor.
- */
- public static final int BRIGHTNESS_MODE_SENSOR = 1;
-
- private final Light mLights[] = new Light[LIGHT_ID_COUNT];
-
- public final class Light {
-
- private Light(int id) {
+ private LightImpl(int id) {
mId = id;
}
+ @Override
public void setBrightness(int brightness) {
setBrightness(brightness, BRIGHTNESS_MODE_USER);
}
+ @Override
public void setBrightness(int brightness, int brightnessMode) {
synchronized (this) {
int color = brightness & 0x000000ff;
@@ -75,23 +54,26 @@
}
}
+ @Override
public void setColor(int color) {
synchronized (this) {
setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, 0);
}
}
+ @Override
public void setFlashing(int color, int mode, int onMS, int offMS) {
synchronized (this) {
setLightLocked(color, mode, onMS, offMS, BRIGHTNESS_MODE_USER);
}
}
-
+ @Override
public void pulse() {
pulse(0x00ffffff, 7);
}
+ @Override
public void pulse(int color, int onMS) {
synchronized (this) {
if (mColor == 0 && !mFlashing) {
@@ -101,6 +83,7 @@
}
}
+ @Override
public void turnOff() {
synchronized (this) {
setLightLocked(0, LIGHT_FLASH_NONE, 0, 0, 0);
@@ -153,9 +136,10 @@
}
public void setFlashlightEnabled(boolean on) {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.FLASHLIGHT)
+ final Context context = getContext();
+ if (context.checkCallingOrSelfPermission(android.Manifest.permission.FLASHLIGHT)
!= PackageManager.PERMISSION_GRANTED &&
- mContext.checkCallingOrSelfPermission(android.Manifest.permission.HARDWARE_TEST)
+ context.checkCallingOrSelfPermission(android.Manifest.permission.HARDWARE_TEST)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires FLASHLIGHT or HARDWARE_TEST permission");
}
@@ -172,31 +156,41 @@
}
};
- LightsService(Context context) {
-
+ @Override
+ public void onCreate(Context context) {
mNativePointer = init_native();
- mContext = context;
- ServiceManager.addService("hardware", mLegacyFlashlightHack);
-
- for (int i = 0; i < LIGHT_ID_COUNT; i++) {
- mLights[i] = new Light(i);
+ for (int i = 0; i < LightsManager.LIGHT_ID_COUNT; i++) {
+ mLights[i] = new LightImpl(i);
}
}
+ @Override
+ public void onStart() {
+ publishBinderService("hardware", mLegacyFlashlightHack);
+ publishLocalService(LightsManager.class, mService);
+ }
+
+ private final LightsManager mService = new LightsManager() {
+ @Override
+ public com.android.server.lights.Light getLight(int id) {
+ if (id < LIGHT_ID_COUNT) {
+ return mLights[id];
+ } else {
+ return null;
+ }
+ }
+ };
+
protected void finalize() throws Throwable {
finalize_native(mNativePointer);
super.finalize();
}
- public Light getLight(int id) {
- return mLights[id];
- }
-
private Handler mH = new Handler() {
@Override
public void handleMessage(Message msg) {
- Light light = (Light)msg.obj;
+ LightImpl light = (LightImpl)msg.obj;
light.stopFlashing();
}
};
@@ -204,10 +198,8 @@
private static native long init_native();
private static native void finalize_native(long ptr);
- private static native void setLight_native(long ptr, int light, int color, int mode,
+ static native void setLight_native(long ptr, int light, int color, int mode,
int onMS, int offMS, int brightnessMode);
- private final Context mContext;
-
private long mNativePointer;
}
diff --git a/services/java/com/android/server/location/ComprehensiveCountryDetector.java b/services/core/java/com/android/server/location/ComprehensiveCountryDetector.java
similarity index 100%
rename from services/java/com/android/server/location/ComprehensiveCountryDetector.java
rename to services/core/java/com/android/server/location/ComprehensiveCountryDetector.java
diff --git a/services/java/com/android/server/location/CountryDetectorBase.java b/services/core/java/com/android/server/location/CountryDetectorBase.java
similarity index 100%
rename from services/java/com/android/server/location/CountryDetectorBase.java
rename to services/core/java/com/android/server/location/CountryDetectorBase.java
diff --git a/services/java/com/android/server/location/FlpHardwareProvider.java b/services/core/java/com/android/server/location/FlpHardwareProvider.java
similarity index 100%
rename from services/java/com/android/server/location/FlpHardwareProvider.java
rename to services/core/java/com/android/server/location/FlpHardwareProvider.java
diff --git a/services/java/com/android/server/location/FusedLocationHardwareSecure.java b/services/core/java/com/android/server/location/FusedLocationHardwareSecure.java
similarity index 100%
rename from services/java/com/android/server/location/FusedLocationHardwareSecure.java
rename to services/core/java/com/android/server/location/FusedLocationHardwareSecure.java
diff --git a/services/java/com/android/server/location/FusedProxy.java b/services/core/java/com/android/server/location/FusedProxy.java
similarity index 100%
rename from services/java/com/android/server/location/FusedProxy.java
rename to services/core/java/com/android/server/location/FusedProxy.java
diff --git a/services/java/com/android/server/location/GeocoderProxy.java b/services/core/java/com/android/server/location/GeocoderProxy.java
similarity index 100%
rename from services/java/com/android/server/location/GeocoderProxy.java
rename to services/core/java/com/android/server/location/GeocoderProxy.java
diff --git a/services/java/com/android/server/location/GeofenceManager.java b/services/core/java/com/android/server/location/GeofenceManager.java
similarity index 100%
rename from services/java/com/android/server/location/GeofenceManager.java
rename to services/core/java/com/android/server/location/GeofenceManager.java
diff --git a/services/java/com/android/server/location/GeofenceProxy.java b/services/core/java/com/android/server/location/GeofenceProxy.java
similarity index 100%
rename from services/java/com/android/server/location/GeofenceProxy.java
rename to services/core/java/com/android/server/location/GeofenceProxy.java
diff --git a/services/java/com/android/server/location/GeofenceState.java b/services/core/java/com/android/server/location/GeofenceState.java
similarity index 100%
rename from services/java/com/android/server/location/GeofenceState.java
rename to services/core/java/com/android/server/location/GeofenceState.java
diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/core/java/com/android/server/location/GpsLocationProvider.java
similarity index 100%
rename from services/java/com/android/server/location/GpsLocationProvider.java
rename to services/core/java/com/android/server/location/GpsLocationProvider.java
diff --git a/services/java/com/android/server/location/GpsXtraDownloader.java b/services/core/java/com/android/server/location/GpsXtraDownloader.java
similarity index 100%
rename from services/java/com/android/server/location/GpsXtraDownloader.java
rename to services/core/java/com/android/server/location/GpsXtraDownloader.java
diff --git a/services/java/com/android/server/location/LocationBasedCountryDetector.java b/services/core/java/com/android/server/location/LocationBasedCountryDetector.java
similarity index 100%
rename from services/java/com/android/server/location/LocationBasedCountryDetector.java
rename to services/core/java/com/android/server/location/LocationBasedCountryDetector.java
diff --git a/services/java/com/android/server/location/LocationBlacklist.java b/services/core/java/com/android/server/location/LocationBlacklist.java
similarity index 100%
rename from services/java/com/android/server/location/LocationBlacklist.java
rename to services/core/java/com/android/server/location/LocationBlacklist.java
diff --git a/services/java/com/android/server/location/LocationFudger.java b/services/core/java/com/android/server/location/LocationFudger.java
similarity index 100%
rename from services/java/com/android/server/location/LocationFudger.java
rename to services/core/java/com/android/server/location/LocationFudger.java
diff --git a/services/java/com/android/server/location/LocationProviderInterface.java b/services/core/java/com/android/server/location/LocationProviderInterface.java
similarity index 100%
rename from services/java/com/android/server/location/LocationProviderInterface.java
rename to services/core/java/com/android/server/location/LocationProviderInterface.java
diff --git a/services/java/com/android/server/location/LocationProviderProxy.java b/services/core/java/com/android/server/location/LocationProviderProxy.java
similarity index 100%
rename from services/java/com/android/server/location/LocationProviderProxy.java
rename to services/core/java/com/android/server/location/LocationProviderProxy.java
diff --git a/services/java/com/android/server/location/MockProvider.java b/services/core/java/com/android/server/location/MockProvider.java
similarity index 100%
rename from services/java/com/android/server/location/MockProvider.java
rename to services/core/java/com/android/server/location/MockProvider.java
diff --git a/services/java/com/android/server/location/PassiveProvider.java b/services/core/java/com/android/server/location/PassiveProvider.java
similarity index 100%
rename from services/java/com/android/server/location/PassiveProvider.java
rename to services/core/java/com/android/server/location/PassiveProvider.java
diff --git a/services/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java
similarity index 100%
rename from services/java/com/android/server/media/MediaRouterService.java
rename to services/core/java/com/android/server/media/MediaRouterService.java
diff --git a/services/java/com/android/server/media/RemoteDisplayProviderProxy.java b/services/core/java/com/android/server/media/RemoteDisplayProviderProxy.java
similarity index 100%
rename from services/java/com/android/server/media/RemoteDisplayProviderProxy.java
rename to services/core/java/com/android/server/media/RemoteDisplayProviderProxy.java
diff --git a/services/java/com/android/server/media/RemoteDisplayProviderWatcher.java b/services/core/java/com/android/server/media/RemoteDisplayProviderWatcher.java
similarity index 100%
rename from services/java/com/android/server/media/RemoteDisplayProviderWatcher.java
rename to services/core/java/com/android/server/media/RemoteDisplayProviderWatcher.java
diff --git a/services/java/com/android/server/net/LockdownVpnTracker.java b/services/core/java/com/android/server/net/LockdownVpnTracker.java
similarity index 100%
rename from services/java/com/android/server/net/LockdownVpnTracker.java
rename to services/core/java/com/android/server/net/LockdownVpnTracker.java
diff --git a/services/java/com/android/server/net/NetworkIdentitySet.java b/services/core/java/com/android/server/net/NetworkIdentitySet.java
similarity index 100%
rename from services/java/com/android/server/net/NetworkIdentitySet.java
rename to services/core/java/com/android/server/net/NetworkIdentitySet.java
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
similarity index 100%
rename from services/java/com/android/server/net/NetworkPolicyManagerService.java
rename to services/core/java/com/android/server/net/NetworkPolicyManagerService.java
diff --git a/services/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java
similarity index 100%
rename from services/java/com/android/server/net/NetworkStatsCollection.java
rename to services/core/java/com/android/server/net/NetworkStatsCollection.java
diff --git a/services/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java
similarity index 100%
rename from services/java/com/android/server/net/NetworkStatsRecorder.java
rename to services/core/java/com/android/server/net/NetworkStatsRecorder.java
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
similarity index 100%
rename from services/java/com/android/server/net/NetworkStatsService.java
rename to services/core/java/com/android/server/net/NetworkStatsService.java
diff --git a/services/core/java/com/android/server/notification/NotificationDelegate.java b/services/core/java/com/android/server/notification/NotificationDelegate.java
new file mode 100644
index 0000000..df2aaca
--- /dev/null
+++ b/services/core/java/com/android/server/notification/NotificationDelegate.java
@@ -0,0 +1,27 @@
+/**
+ * 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.server.notification;
+
+public interface NotificationDelegate {
+ void onSetDisabled(int status);
+ void onClearAll();
+ void onNotificationClick(String pkg, String tag, int id);
+ void onNotificationClear(String pkg, String tag, int id);
+ void onNotificationError(String pkg, String tag, int id,
+ int uid, int initialPid, String message);
+ void onPanelRevealed();
+}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerInternal.java b/services/core/java/com/android/server/notification/NotificationManagerInternal.java
new file mode 100644
index 0000000..92ffdcc
--- /dev/null
+++ b/services/core/java/com/android/server/notification/NotificationManagerInternal.java
@@ -0,0 +1,8 @@
+package com.android.server.notification;
+
+import android.app.Notification;
+
+public interface NotificationManagerInternal {
+ void enqueueNotification(String pkg, String basePkg, int callingUid, int callingPid,
+ String tag, int id, Notification notification, int[] idReceived, int userId);
+}
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
similarity index 78%
rename from services/java/com/android/server/NotificationManagerService.java
rename to services/core/java/com/android/server/notification/NotificationManagerService.java
index 0438675..db4cf31d 100644
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server;
+package com.android.server.notification;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.END_TAG;
@@ -47,7 +47,6 @@
import android.database.ContentObserver;
import android.graphics.Bitmap;
import android.media.AudioManager;
-import android.media.IAudioService;
import android.media.IRingtonePlayer;
import android.net.Uri;
import android.os.Binder;
@@ -56,9 +55,7 @@
import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.UserHandle;
-import android.os.UserManager;
import android.os.Vibrator;
import android.provider.Settings;
import android.service.notification.INotificationListener;
@@ -78,6 +75,12 @@
import com.android.internal.R;
import com.android.internal.notification.NotificationScorer;
+import com.android.server.EventLogTags;
+import com.android.server.statusbar.StatusBarManagerInternal;
+import com.android.server.SystemService;
+import com.android.server.lights.Light;
+import com.android.server.lights.LightsManager;
+
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -99,66 +102,61 @@
import libcore.io.IoUtils;
-
/** {@hide} */
-public class NotificationManagerService extends INotificationManager.Stub
-{
- private static final String TAG = "NotificationService";
- private static final boolean DBG = false;
+public class NotificationManagerService extends SystemService {
+ static final String TAG = "NotificationService";
+ static final boolean DBG = false;
- private static final int MAX_PACKAGE_NOTIFICATIONS = 50;
+ static final int MAX_PACKAGE_NOTIFICATIONS = 50;
// message codes
- private static final int MESSAGE_TIMEOUT = 2;
+ static final int MESSAGE_TIMEOUT = 2;
- private static final int LONG_DELAY = 3500; // 3.5 seconds
- private static final int SHORT_DELAY = 2000; // 2 seconds
+ static final int LONG_DELAY = 3500; // 3.5 seconds
+ static final int SHORT_DELAY = 2000; // 2 seconds
- private static final long[] DEFAULT_VIBRATE_PATTERN = {0, 250, 250, 250};
- private static final int VIBRATE_PATTERN_MAXLEN = 8 * 2 + 1; // up to eight bumps
+ static final long[] DEFAULT_VIBRATE_PATTERN = {0, 250, 250, 250};
+ static final int VIBRATE_PATTERN_MAXLEN = 8 * 2 + 1; // up to eight bumps
- private static final int DEFAULT_STREAM_TYPE = AudioManager.STREAM_NOTIFICATION;
- private static final boolean SCORE_ONGOING_HIGHER = false;
+ static final int DEFAULT_STREAM_TYPE = AudioManager.STREAM_NOTIFICATION;
+ static final boolean SCORE_ONGOING_HIGHER = false;
- private static final int JUNK_SCORE = -1000;
- private static final int NOTIFICATION_PRIORITY_MULTIPLIER = 10;
- private static final int SCORE_DISPLAY_THRESHOLD = Notification.PRIORITY_MIN * NOTIFICATION_PRIORITY_MULTIPLIER;
+ static final int JUNK_SCORE = -1000;
+ static final int NOTIFICATION_PRIORITY_MULTIPLIER = 10;
+ static final int SCORE_DISPLAY_THRESHOLD = Notification.PRIORITY_MIN * NOTIFICATION_PRIORITY_MULTIPLIER;
// Notifications with scores below this will not interrupt the user, either via LED or
// sound or vibration
- private static final int SCORE_INTERRUPTION_THRESHOLD =
+ static final int SCORE_INTERRUPTION_THRESHOLD =
Notification.PRIORITY_LOW * NOTIFICATION_PRIORITY_MULTIPLIER;
- private static final boolean ENABLE_BLOCKED_NOTIFICATIONS = true;
- private static final boolean ENABLE_BLOCKED_TOASTS = true;
+ static final boolean ENABLE_BLOCKED_NOTIFICATIONS = true;
+ static final boolean ENABLE_BLOCKED_TOASTS = true;
- private static final String ENABLED_NOTIFICATION_LISTENERS_SEPARATOR = ":";
+ static final String ENABLED_NOTIFICATION_LISTENERS_SEPARATOR = ":";
- final Context mContext;
- final IActivityManager mAm;
- final UserManager mUserManager;
+ private IActivityManager mAm;
+ AudioManager mAudioManager;
+ StatusBarManagerInternal mStatusBar;
+ Vibrator mVibrator;
+
final IBinder mForegroundToken = new Binder();
-
private WorkerHandler mHandler;
- private StatusBarManagerService mStatusBar;
- private LightsService.Light mNotificationLight;
- private LightsService.Light mAttentionLight;
+ private Light mNotificationLight;
+ Light mAttentionLight;
private int mDefaultNotificationColor;
private int mDefaultNotificationLedOn;
+
private int mDefaultNotificationLedOff;
-
private long[] mDefaultVibrationPattern;
+
private long[] mFallbackVibrationPattern;
+ boolean mSystemReady;
- private boolean mSystemReady;
- private int mDisabledNotifications;
-
- private NotificationRecord mSoundNotification;
- private NotificationRecord mVibrateNotification;
-
- private IAudioService mAudioService;
- private Vibrator mVibrator;
+ int mDisabledNotifications;
+ NotificationRecord mSoundNotification;
+ NotificationRecord mVibrateNotification;
// for enabling and disabling notification pulse behavior
private boolean mScreenOn = true;
@@ -166,15 +164,15 @@
private boolean mNotificationPulseEnabled;
// used as a mutex for access to all active notifications & listeners
- private final ArrayList<NotificationRecord> mNotificationList =
+ final ArrayList<NotificationRecord> mNotificationList =
new ArrayList<NotificationRecord>();
- private ArrayList<ToastRecord> mToastQueue;
+ final ArrayList<ToastRecord> mToastQueue = new ArrayList<ToastRecord>();
- private ArrayList<NotificationRecord> mLights = new ArrayList<NotificationRecord>();
- private NotificationRecord mLedNotification;
+ ArrayList<NotificationRecord> mLights = new ArrayList<NotificationRecord>();
+ NotificationRecord mLedNotification;
- private final AppOpsManager mAppOps;
+ private AppOpsManager mAppOps;
// contains connections to all connected listeners, including app services
// and system listeners
@@ -202,9 +200,9 @@
private static final String TAG_PACKAGE = "package";
private static final String ATTR_NAME = "name";
- private final ArrayList<NotificationScorer> mScorers = new ArrayList<NotificationScorer>();
+ final ArrayList<NotificationScorer> mScorers = new ArrayList<NotificationScorer>();
- private class NotificationListenerInfo implements DeathRecipient {
+ private class NotificationListenerInfo implements IBinder.DeathRecipient {
INotificationListener listener;
ComponentName component;
int userid;
@@ -262,7 +260,7 @@
public void binderDied() {
if (connection == null) {
// This is not a service; it won't be recreated. We can give up this connection.
- unregisterListener(this.listener, this.userid);
+ unregisterListenerImpl(this.listener, this.userid);
}
}
@@ -400,12 +398,14 @@
tag = parser.getName();
if (type == START_TAG) {
if (TAG_BODY.equals(tag)) {
- version = Integer.parseInt(parser.getAttributeValue(null, ATTR_VERSION));
+ 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));
+ mBlockedPackages.add(
+ parser.getAttributeValue(null, ATTR_NAME));
} else if (TAG_BLOCKED_PKGS.equals(tag) && type == END_TAG) {
break;
}
@@ -428,15 +428,6 @@
}
}
- /**
- * Use this when you just want to know if notifications are OK for this package.
- */
- public boolean areNotificationsEnabledForPackage(String pkg, int uid) {
- checkCallerIsSystem();
- return (mAppOps.checkOpNoThrow(AppOpsManager.OP_POST_NOTIFICATION, uid, pkg)
- == AppOpsManager.MODE_ALLOWED);
- }
-
/** Use this when you actually want to post a notification or toast.
*
* Unchecked. Not exposed via Binder, but can be called in the course of enqueue*().
@@ -450,21 +441,6 @@
return true;
}
- public void setNotificationsEnabledForPackage(String pkg, int uid, boolean enabled) {
- checkCallerIsSystem();
-
- Slog.v(TAG, (enabled?"en":"dis") + "abling notifications for " + pkg);
-
- mAppOps.setMode(AppOpsManager.OP_POST_NOTIFICATION, uid, pkg,
- enabled ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED);
-
- // Now, cancel any outstanding notifications that are part of a just-disabled app
- if (ENABLE_BLOCKED_NOTIFICATIONS && !enabled) {
- cancelAllNotificationsInt(pkg, 0, 0, true, UserHandle.getUserId(uid));
- }
- }
-
-
private static String idDebugString(Context baseContext, String packageName, int id) {
Context c = null;
@@ -490,57 +466,6 @@
}
}
- /**
- * System-only API for getting a list of current (i.e. not cleared) notifications.
- *
- * Requires ACCESS_NOTIFICATIONS which is signature|system.
- */
- @Override
- public StatusBarNotification[] getActiveNotifications(String callingPkg) {
- // enforce() will ensure the calling uid has the correct permission
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NOTIFICATIONS,
- "NotificationManagerService.getActiveNotifications");
-
- StatusBarNotification[] tmp = null;
- int uid = Binder.getCallingUid();
-
- // noteOp will check to make sure the callingPkg matches the uid
- if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ACCESS_NOTIFICATIONS, uid, callingPkg)
- == AppOpsManager.MODE_ALLOWED) {
- synchronized (mNotificationList) {
- tmp = new StatusBarNotification[mNotificationList.size()];
- final int N = mNotificationList.size();
- for (int i=0; i<N; i++) {
- tmp[i] = mNotificationList.get(i).sbn;
- }
- }
- }
- return tmp;
- }
-
- /**
- * System-only API for getting a list of recent (cleared, no longer shown) notifications.
- *
- * Requires ACCESS_NOTIFICATIONS which is signature|system.
- */
- @Override
- public StatusBarNotification[] getHistoricalNotifications(String callingPkg, int count) {
- // enforce() will ensure the calling uid has the correct permission
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NOTIFICATIONS,
- "NotificationManagerService.getHistoricalNotifications");
-
- StatusBarNotification[] tmp = null;
- int uid = Binder.getCallingUid();
-
- // noteOp will check to make sure the callingPkg matches the uid
- if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ACCESS_NOTIFICATIONS, uid, callingPkg)
- == AppOpsManager.MODE_ALLOWED) {
- synchronized (mArchive) {
- tmp = mArchive.getArray(count);
- }
- }
- return tmp;
- }
/**
* Remove notification access for any services that no longer exist.
@@ -548,12 +473,12 @@
void disableNonexistentListeners() {
int currentUser = ActivityManager.getCurrentUser();
String flatIn = Settings.Secure.getStringForUser(
- mContext.getContentResolver(),
+ getContext().getContentResolver(),
Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
currentUser);
if (!TextUtils.isEmpty(flatIn)) {
if (DBG) Slog.v(TAG, "flat before: " + flatIn);
- PackageManager pm = mContext.getPackageManager();
+ PackageManager pm = getContext().getPackageManager();
List<ResolveInfo> installedServices = pm.queryIntentServicesAsUser(
new Intent(NotificationListenerService.SERVICE_INTERFACE),
PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
@@ -589,7 +514,7 @@
}
if (DBG) Slog.v(TAG, "flat after: " + flatOut);
if (!flatIn.equals(flatOut)) {
- Settings.Secure.putStringForUser(mContext.getContentResolver(),
+ Settings.Secure.putStringForUser(getContext().getContentResolver(),
Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
flatOut, currentUser);
}
@@ -603,7 +528,7 @@
void rebindListenerServices() {
final int currentUser = ActivityManager.getCurrentUser();
String flat = Settings.Secure.getStringForUser(
- mContext.getContentResolver(),
+ getContext().getContentResolver(),
Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
currentUser);
@@ -652,28 +577,6 @@
}
}
- /**
- * Register a listener binder directly with the notification manager.
- *
- * Only works with system callers. Apps should extend
- * {@link android.service.notification.NotificationListenerService}.
- */
- @Override
- public void registerListener(final INotificationListener listener,
- final ComponentName component, final int userid) {
- checkCallerIsSystem();
-
- synchronized (mNotificationList) {
- try {
- NotificationListenerInfo info
- = new NotificationListenerInfo(listener, component, userid, true);
- listener.asBinder().linkToDeath(info, 0);
- mListeners.add(info);
- } catch (RemoteException e) {
- // already dead
- }
- }
- }
/**
* Version of registerListener that takes the name of a
@@ -703,7 +606,7 @@
if (DBG) Slog.v(TAG, " disconnecting old listener: " + info.listener);
mListeners.remove(i);
if (info.connection != null) {
- mContext.unbindService(info.connection);
+ getContext().unbindService(info.connection);
}
}
}
@@ -713,21 +616,25 @@
intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
R.string.notification_listener_binding_label);
- intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
- mContext, 0, new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS), 0));
+
+ final PendingIntent pendingIntent = PendingIntent.getActivity(
+ getContext(), 0, new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS), 0);
+ intent.putExtra(Intent.EXTRA_CLIENT_INTENT, pendingIntent);
try {
if (DBG) Slog.v(TAG, "binding: " + intent);
- if (!mContext.bindServiceAsUser(intent,
+ if (!getContext().bindServiceAsUser(intent,
new ServiceConnection() {
INotificationListener mListener;
+
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
synchronized (mNotificationList) {
mServicesBinding.remove(servicesBindingTag);
try {
mListener = INotificationListener.Stub.asInterface(service);
- NotificationListenerInfo info = new NotificationListenerInfo(
+ NotificationListenerInfo info
+ = new NotificationListenerInfo(
mListener, name, userid, this);
service.linkToDeath(info, 0);
mListeners.add(info);
@@ -756,28 +663,6 @@
}
}
- /**
- * Remove a listener binder directly
- */
- @Override
- public void unregisterListener(INotificationListener listener, int userid) {
- // no need to check permissions; if your listener binder is in the list,
- // that's proof that you had permission to add it in the first place
-
- synchronized (mNotificationList) {
- final int N = mListeners.size();
- for (int i=N-1; i>=0; i--) {
- final NotificationListenerInfo info = mListeners.get(i);
- if (info.listener.asBinder() == listener.asBinder()
- && info.userid == userid) {
- mListeners.remove(i);
- if (info.connection != null) {
- mContext.unbindService(info.connection);
- }
- }
- }
- }
- }
/**
* Remove a listener service for the given user by ComponentName
@@ -794,7 +679,7 @@
mListeners.remove(i);
if (info.connection != null) {
try {
- mContext.unbindService(info.connection);
+ getContext().unbindService(info.connection);
} catch (IllegalArgumentException ex) {
// something happened to the service: we think we have a connection
// but it's bogus.
@@ -809,7 +694,7 @@
/**
* asynchronously notify all listeners about a new notification
*/
- private void notifyPostedLocked(NotificationRecord n) {
+ void notifyPostedLocked(NotificationRecord n) {
// make a copy in case changes are made to the underlying Notification object
final StatusBarNotification sbn = n.sbn.clone();
for (final NotificationListenerInfo info : mListeners) {
@@ -824,7 +709,7 @@
/**
* asynchronously notify all listeners about a removed notification
*/
- private void notifyRemovedLocked(NotificationRecord n) {
+ void notifyRemovedLocked(NotificationRecord n) {
// make a copy in case changes are made to the underlying Notification object
// NOTE: this copy is lightweight: it doesn't include heavyweight parts of the notification
final StatusBarNotification sbn_light = n.sbn.cloneLight();
@@ -850,66 +735,7 @@
throw new SecurityException("Disallowed call from unknown listener: " + listener);
}
- /**
- * Allow an INotificationListener to simulate a "clear all" operation.
- *
- * {@see com.android.server.StatusBarManagerService.NotificationCallbacks#onClearAllNotifications}
- *
- * @param token The binder for the listener, to check that the caller is allowed
- */
- public void cancelAllNotificationsFromListener(INotificationListener token) {
- NotificationListenerInfo info = checkListenerToken(token);
- long identity = Binder.clearCallingIdentity();
- try {
- cancelAll(info.userid);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
- /**
- * Allow an INotificationListener to simulate clearing (dismissing) a single notification.
- *
- * {@see com.android.server.StatusBarManagerService.NotificationCallbacks#onNotificationClear}
- *
- * @param token The binder for the listener, to check that the caller is allowed
- */
- public void cancelNotificationFromListener(INotificationListener token, String pkg, String tag, int id) {
- NotificationListenerInfo info = checkListenerToken(token);
- long identity = Binder.clearCallingIdentity();
- try {
- cancelNotification(pkg, tag, id, 0,
- Notification.FLAG_ONGOING_EVENT | Notification.FLAG_FOREGROUND_SERVICE,
- true,
- info.userid);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
- /**
- * Allow an INotificationListener to request the list of outstanding notifications seen by
- * the current user. Useful when starting up, after which point the listener callbacks should
- * be used.
- *
- * @param token The binder for the listener, to check that the caller is allowed
- */
- public StatusBarNotification[] getActiveNotificationsFromListener(INotificationListener token) {
- NotificationListenerInfo info = checkListenerToken(token);
-
- StatusBarNotification[] result = new StatusBarNotification[0];
- ArrayList<StatusBarNotification> list = new ArrayList<StatusBarNotification>();
- synchronized (mNotificationList) {
- final int N = mNotificationList.size();
- for (int i=0; i<N; i++) {
- StatusBarNotification sbn = mNotificationList.get(i).sbn;
- if (info.enabledAndUserMatches(sbn)) {
- list.add(sbn);
- }
- }
- }
- return list.toArray(result);
- }
// -- end of listener APIs --
@@ -992,8 +818,8 @@
return String.format(
"NotificationRecord(0x%08x: pkg=%s user=%s id=%d tag=%s score=%d: %s)",
System.identityHashCode(this),
- this.sbn.getPackageName(), this.sbn.getUser(), this.sbn.getId(), this.sbn.getTag(),
- this.sbn.getScore(), this.sbn.getNotification());
+ this.sbn.getPackageName(), this.sbn.getUser(), this.sbn.getId(),
+ this.sbn.getTag(), this.sbn.getScore(), this.sbn.getNotification());
}
}
@@ -1031,9 +857,9 @@
}
}
- private StatusBarManagerService.NotificationCallbacks mNotificationCallbacks
- = new StatusBarManagerService.NotificationCallbacks() {
+ private final NotificationDelegate mNotificationDelegate = new NotificationDelegate() {
+ @Override
public void onSetDisabled(int status) {
synchronized (mNotificationList) {
mDisabledNotifications = status;
@@ -1041,7 +867,7 @@
// cancel whatever's going on
long identity = Binder.clearCallingIdentity();
try {
- final IRingtonePlayer player = mAudioService.getRingtonePlayer();
+ final IRingtonePlayer player = mAudioManager.getRingtonePlayer();
if (player != null) {
player.stopAsync();
}
@@ -1060,12 +886,14 @@
}
}
+ @Override
public void onClearAll() {
// XXX to be totally correct, the caller should tell us which user
// this is for.
cancelAll(ActivityManager.getCurrentUser());
}
+ @Override
public void onNotificationClick(String pkg, String tag, int id) {
// XXX to be totally correct, the caller should tell us which user
// this is for.
@@ -1074,6 +902,7 @@
ActivityManager.getCurrentUser());
}
+ @Override
public void onNotificationClear(String pkg, String tag, int id) {
// XXX to be totally correct, the caller should tell us which user
// this is for.
@@ -1082,6 +911,7 @@
true, ActivityManager.getCurrentUser());
}
+ @Override
public void onPanelRevealed() {
synchronized (mNotificationList) {
// sound
@@ -1089,7 +919,7 @@
long identity = Binder.clearCallingIdentity();
try {
- final IRingtonePlayer player = mAudioService.getRingtonePlayer();
+ final IRingtonePlayer player = mAudioManager.getRingtonePlayer();
if (player != null) {
player.stopAsync();
}
@@ -1114,6 +944,7 @@
}
}
+ @Override
public void onNotificationError(String pkg, String tag, int id,
int uid, int initialPid, String message) {
Slog.d(TAG, "onNotification error pkg=" + pkg + " tag=" + tag + " id=" + id
@@ -1168,7 +999,7 @@
if (packageChanged) {
// We cancel notifications for packages which have just been disabled
try {
- final int enabled = mContext.getPackageManager()
+ final int enabled = getContext().getPackageManager()
.getApplicationEnabledSetting(pkgName);
if (enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED
|| enabled == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
@@ -1244,7 +1075,7 @@
}
void observe() {
- ContentResolver resolver = mContext.getContentResolver();
+ ContentResolver resolver = getContext().getContentResolver();
resolver.registerContentObserver(NOTIFICATION_LIGHT_PULSE_URI,
false, this, UserHandle.USER_ALL);
resolver.registerContentObserver(ENABLED_NOTIFICATION_LISTENERS_URI,
@@ -1257,7 +1088,7 @@
}
public void update(Uri uri) {
- ContentResolver resolver = mContext.getContentResolver();
+ ContentResolver resolver = getContext().getContentResolver();
if (uri == null || NOTIFICATION_LIGHT_PULSE_URI.equals(uri)) {
boolean pulseEnabled = Settings.System.getInt(resolver,
Settings.System.NOTIFICATION_LIGHT_PULSE, 0) != 0;
@@ -1287,28 +1118,24 @@
return out;
}
- NotificationManagerService(Context context, StatusBarManagerService statusBar,
- LightsService lights)
- {
- super();
- mContext = context;
- mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
+ @Override
+ public void onStart() {
mAm = ActivityManagerNative.getDefault();
- mUserManager = (UserManager)context.getSystemService(Context.USER_SERVICE);
- mToastQueue = new ArrayList<ToastRecord>();
- mHandler = new WorkerHandler();
+ mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
+ mVibrator = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);
- mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
+ mHandler = new WorkerHandler();
importOldBlockDb();
- mStatusBar = statusBar;
- statusBar.setNotificationCallbacks(mNotificationCallbacks);
+ mStatusBar = getLocalService(StatusBarManagerInternal.class);
+ mStatusBar.setNotificationDelegate(mNotificationDelegate);
- mNotificationLight = lights.getLight(LightsService.LIGHT_ID_NOTIFICATIONS);
- mAttentionLight = lights.getLight(LightsService.LIGHT_ID_ATTENTION);
+ final LightsManager lights = getLocalService(LightsManager.class);
+ mNotificationLight = lights.getLight(LightsManager.LIGHT_ID_NOTIFICATIONS);
+ mAttentionLight = lights.getLight(LightsManager.LIGHT_ID_ATTENTION);
- Resources resources = mContext.getResources();
+ Resources resources = getContext().getResources();
mDefaultNotificationColor = resources.getColor(
R.color.config_defaultNotificationColor);
mDefaultNotificationLedOn = resources.getInteger(
@@ -1330,7 +1157,7 @@
// After that, including subsequent boots, init with notifications turned on.
// This works on the first boot because the setup wizard will toggle this
// flag at least once and we'll go back to 0 after that.
- if (0 == Settings.Global.getInt(mContext.getContentResolver(),
+ if (0 == Settings.Global.getInt(getContext().getContentResolver(),
Settings.Global.DEVICE_PROVISIONED, 0)) {
mDisabledNotifications = StatusBarManager.DISABLE_NOTIFICATION_ALERTS;
}
@@ -1343,7 +1170,7 @@
filter.addAction(Intent.ACTION_USER_PRESENT);
filter.addAction(Intent.ACTION_USER_STOPPED);
filter.addAction(Intent.ACTION_USER_SWITCHED);
- mContext.registerReceiver(mIntentReceiver, filter);
+ getContext().registerReceiver(mIntentReceiver, filter);
IntentFilter pkgFilter = new IntentFilter();
pkgFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
pkgFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
@@ -1351,9 +1178,9 @@
pkgFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
pkgFilter.addDataScheme("package");
- mContext.registerReceiver(mIntentReceiver, pkgFilter);
+ getContext().registerReceiver(mIntentReceiver, pkgFilter);
IntentFilter sdFilter = new IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
- mContext.registerReceiver(mIntentReceiver, sdFilter);
+ getContext().registerReceiver(mIntentReceiver, sdFilter);
mSettingsObserver = new SettingsObserver(mHandler);
mSettingsObserver.observe();
@@ -1363,9 +1190,9 @@
R.array.config_notificationScorers);
for (String scorerName : notificationScorerNames) {
try {
- Class<?> scorerClass = mContext.getClassLoader().loadClass(scorerName);
+ Class<?> scorerClass = getContext().getClassLoader().loadClass(scorerName);
NotificationScorer scorer = (NotificationScorer) scorerClass.newInstance();
- scorer.initialize(mContext);
+ scorer.initialize(getContext());
mScorers.add(scorer);
} catch (ClassNotFoundException e) {
Slog.w(TAG, "Couldn't find scorer " + scorerName + ".", e);
@@ -1375,6 +1202,9 @@
Slog.w(TAG, "Problem accessing scorer " + scorerName + ".", e);
}
}
+
+ publishBinderService(Context.NOTIFICATION_SERVICE, mService);
+ publishLocalService(NotificationManagerInternal.class, mInternalService);
}
/**
@@ -1383,12 +1213,12 @@
private void importOldBlockDb() {
loadBlockDb();
- PackageManager pm = mContext.getPackageManager();
+ PackageManager pm = getContext().getPackageManager();
for (String pkg : mBlockedPackages) {
PackageInfo info = null;
try {
info = pm.getPackageInfo(pkg, 0);
- setNotificationsEnabledForPackage(pkg, info.applicationInfo.uid, false);
+ setNotificationsEnabledForPackageImpl(pkg, info.applicationInfo.uid, false);
} catch (NameNotFoundException e) {
// forget you
}
@@ -1399,244 +1229,421 @@
}
}
- void systemReady() {
- mAudioService = IAudioService.Stub.asInterface(
- ServiceManager.getService(Context.AUDIO_SERVICE));
+ @Override
+ public void onBootPhase(int phase) {
+ if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
+ // no beeping until we're basically done booting
+ mSystemReady = true;
- // no beeping until we're basically done booting
- mSystemReady = true;
+ // Grab our optional AudioService
+ mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
- // make sure our listener services are properly bound
- rebindListenerServices();
- }
-
- // Toasts
- // ============================================================================
- public void enqueueToast(String pkg, ITransientNotification callback, int duration)
- {
- if (DBG) Slog.i(TAG, "enqueueToast pkg=" + pkg + " callback=" + callback + " duration=" + duration);
-
- if (pkg == null || callback == null) {
- Slog.e(TAG, "Not doing toast. pkg=" + pkg + " callback=" + callback);
- return ;
- }
-
- final boolean isSystemToast = isCallerSystem() || ("android".equals(pkg));
-
- if (ENABLE_BLOCKED_TOASTS && !noteNotificationOp(pkg, Binder.getCallingUid())) {
- if (!isSystemToast) {
- Slog.e(TAG, "Suppressing toast from package " + pkg + " by user request.");
- return;
- }
- }
-
- synchronized (mToastQueue) {
- int callingPid = Binder.getCallingPid();
- long callingId = Binder.clearCallingIdentity();
- try {
- ToastRecord record;
- int index = indexOfToastLocked(pkg, callback);
- // If it's already in the queue, we update it in place, we don't
- // move it to the end of the queue.
- if (index >= 0) {
- record = mToastQueue.get(index);
- record.update(duration);
- } else {
- // Limit the number of toasts that any given package except the android
- // package can enqueue. Prevents DOS attacks and deals with leaks.
- if (!isSystemToast) {
- int count = 0;
- final int N = mToastQueue.size();
- for (int i=0; i<N; i++) {
- final ToastRecord r = mToastQueue.get(i);
- if (r.pkg.equals(pkg)) {
- count++;
- if (count >= MAX_PACKAGE_NOTIFICATIONS) {
- Slog.e(TAG, "Package has already posted " + count
- + " toasts. Not showing more. Package=" + pkg);
- return;
- }
- }
- }
- }
-
- record = new ToastRecord(callingPid, pkg, callback, duration);
- mToastQueue.add(record);
- index = mToastQueue.size() - 1;
- keepProcessAliveLocked(callingPid);
- }
- // If it's at index 0, it's the current toast. It doesn't matter if it's
- // new or just been updated. Call back and tell it to show itself.
- // If the callback fails, this will remove it from the list, so don't
- // assume that it's valid after this.
- if (index == 0) {
- showNextToastLocked();
- }
- } finally {
- Binder.restoreCallingIdentity(callingId);
- }
+ // make sure our listener services are properly bound
+ rebindListenerServices();
}
}
- public void cancelToast(String pkg, ITransientNotification callback) {
- Slog.i(TAG, "cancelToast pkg=" + pkg + " callback=" + callback);
+ void setNotificationsEnabledForPackageImpl(String pkg, int uid, boolean enabled) {
+ Slog.v(TAG, (enabled?"en":"dis") + "abling notifications for " + pkg);
- if (pkg == null || callback == null) {
- Slog.e(TAG, "Not cancelling notification. pkg=" + pkg + " callback=" + callback);
- return ;
- }
+ mAppOps.setMode(AppOpsManager.OP_POST_NOTIFICATION, uid, pkg,
+ enabled ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED);
- synchronized (mToastQueue) {
- long callingId = Binder.clearCallingIdentity();
- try {
- int index = indexOfToastLocked(pkg, callback);
- if (index >= 0) {
- cancelToastLocked(index);
- } else {
- Slog.w(TAG, "Toast already cancelled. pkg=" + pkg + " callback=" + callback);
- }
- } finally {
- Binder.restoreCallingIdentity(callingId);
- }
+ // Now, cancel any outstanding notifications that are part of a just-disabled app
+ if (ENABLE_BLOCKED_NOTIFICATIONS && !enabled) {
+ cancelAllNotificationsInt(pkg, 0, 0, true, UserHandle.getUserId(uid));
}
}
- private void showNextToastLocked() {
- ToastRecord record = mToastQueue.get(0);
- while (record != null) {
- if (DBG) Slog.d(TAG, "Show pkg=" + record.pkg + " callback=" + record.callback);
- try {
- record.callback.show();
- scheduleTimeoutLocked(record);
- return;
- } catch (RemoteException e) {
- Slog.w(TAG, "Object died trying to show notification " + record.callback
- + " in package " + record.pkg);
- // remove it from the list and let the process die
- int index = mToastQueue.indexOf(record);
- if (index >= 0) {
- mToastQueue.remove(index);
- }
- keepProcessAliveLocked(record.pid);
- if (mToastQueue.size() > 0) {
- record = mToastQueue.get(0);
- } else {
- record = null;
- }
- }
- }
- }
+ private final IBinder mService = new INotificationManager.Stub() {
+ // Toasts
+ // ============================================================================
- private void cancelToastLocked(int index) {
- ToastRecord record = mToastQueue.get(index);
- try {
- record.callback.hide();
- } catch (RemoteException e) {
- Slog.w(TAG, "Object died trying to hide notification " + record.callback
- + " in package " + record.pkg);
- // don't worry about this, we're about to remove it from
- // the list anyway
- }
- mToastQueue.remove(index);
- keepProcessAliveLocked(record.pid);
- if (mToastQueue.size() > 0) {
- // Show the next one. If the callback fails, this will remove
- // it from the list, so don't assume that the list hasn't changed
- // after this point.
- showNextToastLocked();
- }
- }
-
- private void scheduleTimeoutLocked(ToastRecord r)
- {
- mHandler.removeCallbacksAndMessages(r);
- Message m = Message.obtain(mHandler, MESSAGE_TIMEOUT, r);
- long delay = r.duration == Toast.LENGTH_LONG ? LONG_DELAY : SHORT_DELAY;
- mHandler.sendMessageDelayed(m, delay);
- }
-
- private void handleTimeout(ToastRecord record)
- {
- if (DBG) Slog.d(TAG, "Timeout pkg=" + record.pkg + " callback=" + record.callback);
- synchronized (mToastQueue) {
- int index = indexOfToastLocked(record.pkg, record.callback);
- if (index >= 0) {
- cancelToastLocked(index);
- }
- }
- }
-
- // lock on mToastQueue
- private int indexOfToastLocked(String pkg, ITransientNotification callback)
- {
- IBinder cbak = callback.asBinder();
- ArrayList<ToastRecord> list = mToastQueue;
- int len = list.size();
- for (int i=0; i<len; i++) {
- ToastRecord r = list.get(i);
- if (r.pkg.equals(pkg) && r.callback.asBinder() == cbak) {
- return i;
- }
- }
- return -1;
- }
-
- // lock on mToastQueue
- private void keepProcessAliveLocked(int pid)
- {
- int toastCount = 0; // toasts from this pid
- ArrayList<ToastRecord> list = mToastQueue;
- int N = list.size();
- for (int i=0; i<N; i++) {
- ToastRecord r = list.get(i);
- if (r.pid == pid) {
- toastCount++;
- }
- }
- try {
- mAm.setProcessForeground(mForegroundToken, pid, toastCount > 0);
- } catch (RemoteException e) {
- // Shouldn't happen.
- }
- }
-
- private final class WorkerHandler extends Handler
- {
@Override
- public void handleMessage(Message msg)
+ public void enqueueToast(String pkg, ITransientNotification callback, int duration)
{
- switch (msg.what)
- {
- case MESSAGE_TIMEOUT:
- handleTimeout((ToastRecord)msg.obj);
- break;
+ if (DBG) {
+ Slog.i(TAG, "enqueueToast pkg=" + pkg + " callback=" + callback
+ + " duration=" + duration);
}
+
+ if (pkg == null || callback == null) {
+ Slog.e(TAG, "Not doing toast. pkg=" + pkg + " callback=" + callback);
+ return ;
+ }
+
+ final boolean isSystemToast = isCallerSystem() || ("android".equals(pkg));
+
+ if (ENABLE_BLOCKED_TOASTS && !noteNotificationOp(pkg, Binder.getCallingUid())) {
+ if (!isSystemToast) {
+ Slog.e(TAG, "Suppressing toast from package " + pkg + " by user request.");
+ return;
+ }
+ }
+
+ synchronized (mToastQueue) {
+ int callingPid = Binder.getCallingPid();
+ long callingId = Binder.clearCallingIdentity();
+ try {
+ ToastRecord record;
+ int index = indexOfToastLocked(pkg, callback);
+ // If it's already in the queue, we update it in place, we don't
+ // move it to the end of the queue.
+ if (index >= 0) {
+ record = mToastQueue.get(index);
+ record.update(duration);
+ } else {
+ // Limit the number of toasts that any given package except the android
+ // package can enqueue. Prevents DOS attacks and deals with leaks.
+ if (!isSystemToast) {
+ int count = 0;
+ final int N = mToastQueue.size();
+ for (int i=0; i<N; i++) {
+ final ToastRecord r = mToastQueue.get(i);
+ if (r.pkg.equals(pkg)) {
+ count++;
+ if (count >= MAX_PACKAGE_NOTIFICATIONS) {
+ Slog.e(TAG, "Package has already posted " + count
+ + " toasts. Not showing more. Package=" + pkg);
+ return;
+ }
+ }
+ }
+ }
+
+ record = new ToastRecord(callingPid, pkg, callback, duration);
+ mToastQueue.add(record);
+ index = mToastQueue.size() - 1;
+ keepProcessAliveLocked(callingPid);
+ }
+ // If it's at index 0, it's the current toast. It doesn't matter if it's
+ // new or just been updated. Call back and tell it to show itself.
+ // If the callback fails, this will remove it from the list, so don't
+ // assume that it's valid after this.
+ if (index == 0) {
+ showNextToastLocked();
+ }
+ } finally {
+ Binder.restoreCallingIdentity(callingId);
+ }
+ }
+ }
+
+ @Override
+ public void cancelToast(String pkg, ITransientNotification callback) {
+ Slog.i(TAG, "cancelToast pkg=" + pkg + " callback=" + callback);
+
+ if (pkg == null || callback == null) {
+ Slog.e(TAG, "Not cancelling notification. pkg=" + pkg + " callback=" + callback);
+ return ;
+ }
+
+ synchronized (mToastQueue) {
+ long callingId = Binder.clearCallingIdentity();
+ try {
+ int index = indexOfToastLocked(pkg, callback);
+ if (index >= 0) {
+ cancelToastLocked(index);
+ } else {
+ Slog.w(TAG, "Toast already cancelled. pkg=" + pkg
+ + " callback=" + callback);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(callingId);
+ }
+ }
+ }
+
+ @Override
+ public void enqueueNotificationWithTag(String pkg, String basePkg, String tag, int id,
+ Notification notification, int[] idOut, int userId) throws RemoteException {
+ enqueueNotificationInternal(pkg, basePkg, Binder.getCallingUid(),
+ Binder.getCallingPid(), tag, id, notification, idOut, userId);
+ }
+
+ @Override
+ public void cancelNotificationWithTag(String pkg, String tag, int id, int userId) {
+ checkCallerIsSystemOrSameApp(pkg);
+ userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
+ Binder.getCallingUid(), userId, true, false, "cancelNotificationWithTag", pkg);
+ // Don't allow client applications to cancel foreground service notis.
+ cancelNotification(pkg, tag, id, 0,
+ Binder.getCallingUid() == Process.SYSTEM_UID
+ ? 0 : Notification.FLAG_FOREGROUND_SERVICE, false, userId);
+ }
+
+ @Override
+ public void cancelAllNotifications(String pkg, int userId) {
+ checkCallerIsSystemOrSameApp(pkg);
+
+ userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
+ Binder.getCallingUid(), userId, true, false, "cancelAllNotifications", pkg);
+
+ // Calling from user space, don't allow the canceling of actively
+ // running foreground services.
+ cancelAllNotificationsInt(pkg, 0, Notification.FLAG_FOREGROUND_SERVICE, true, userId);
+ }
+
+ @Override
+ public void setNotificationsEnabledForPackage(String pkg, int uid, boolean enabled) {
+ checkCallerIsSystem();
+
+ setNotificationsEnabledForPackageImpl(pkg, uid, enabled);
+ }
+
+ /**
+ * Use this when you just want to know if notifications are OK for this package.
+ */
+ @Override
+ public boolean areNotificationsEnabledForPackage(String pkg, int uid) {
+ checkCallerIsSystem();
+ return (mAppOps.checkOpNoThrow(AppOpsManager.OP_POST_NOTIFICATION, uid, pkg)
+ == AppOpsManager.MODE_ALLOWED);
+ }
+
+ /**
+ * System-only API for getting a list of current (i.e. not cleared) notifications.
+ *
+ * Requires ACCESS_NOTIFICATIONS which is signature|system.
+ */
+ @Override
+ public StatusBarNotification[] getActiveNotifications(String callingPkg) {
+ // enforce() will ensure the calling uid has the correct permission
+ getContext().enforceCallingOrSelfPermission(
+ android.Manifest.permission.ACCESS_NOTIFICATIONS,
+ "NotificationManagerService.getActiveNotifications");
+
+ StatusBarNotification[] tmp = null;
+ int uid = Binder.getCallingUid();
+
+ // noteOp will check to make sure the callingPkg matches the uid
+ if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ACCESS_NOTIFICATIONS, uid, callingPkg)
+ == AppOpsManager.MODE_ALLOWED) {
+ synchronized (mNotificationList) {
+ tmp = new StatusBarNotification[mNotificationList.size()];
+ final int N = mNotificationList.size();
+ for (int i=0; i<N; i++) {
+ tmp[i] = mNotificationList.get(i).sbn;
+ }
+ }
+ }
+ return tmp;
+ }
+
+ /**
+ * System-only API for getting a list of recent (cleared, no longer shown) notifications.
+ *
+ * Requires ACCESS_NOTIFICATIONS which is signature|system.
+ */
+ @Override
+ public StatusBarNotification[] getHistoricalNotifications(String callingPkg, int count) {
+ // enforce() will ensure the calling uid has the correct permission
+ getContext().enforceCallingOrSelfPermission(
+ android.Manifest.permission.ACCESS_NOTIFICATIONS,
+ "NotificationManagerService.getHistoricalNotifications");
+
+ StatusBarNotification[] tmp = null;
+ int uid = Binder.getCallingUid();
+
+ // noteOp will check to make sure the callingPkg matches the uid
+ if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ACCESS_NOTIFICATIONS, uid, callingPkg)
+ == AppOpsManager.MODE_ALLOWED) {
+ synchronized (mArchive) {
+ tmp = mArchive.getArray(count);
+ }
+ }
+ return tmp;
+ }
+
+ /**
+ * Register a listener binder directly with the notification manager.
+ *
+ * Only works with system callers. Apps should extend
+ * {@link android.service.notification.NotificationListenerService}.
+ */
+ @Override
+ public void registerListener(final INotificationListener listener,
+ final ComponentName component, final int userid) {
+ checkCallerIsSystem();
+ registerListenerImpl(listener, component, userid);
+ }
+
+ /**
+ * Remove a listener binder directly
+ */
+ @Override
+ public void unregisterListener(INotificationListener listener, int userid) {
+ // no need to check permissions; if your listener binder is in the list,
+ // that's proof that you had permission to add it in the first place
+ unregisterListenerImpl(listener, userid);
+ }
+
+ /**
+ * Allow an INotificationListener to simulate a "clear all" operation.
+ *
+ * {@see com.android.server.StatusBarManagerService.NotificationCallbacks#onClearAllNotifications}
+ *
+ * @param token The binder for the listener, to check that the caller is allowed
+ */
+ @Override
+ public void cancelAllNotificationsFromListener(INotificationListener token) {
+ NotificationListenerInfo info = checkListenerToken(token);
+ long identity = Binder.clearCallingIdentity();
+ try {
+ cancelAll(info.userid);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
+ * Allow an INotificationListener to simulate clearing (dismissing) a single notification.
+ *
+ * {@see com.android.server.StatusBarManagerService.NotificationCallbacks#onNotificationClear}
+ *
+ * @param token The binder for the listener, to check that the caller is allowed
+ */
+ @Override
+ public void cancelNotificationFromListener(INotificationListener token, String pkg,
+ String tag, int id) {
+ NotificationListenerInfo info = checkListenerToken(token);
+ long identity = Binder.clearCallingIdentity();
+ try {
+ cancelNotification(pkg, tag, id, 0,
+ Notification.FLAG_ONGOING_EVENT | Notification.FLAG_FOREGROUND_SERVICE,
+ true,
+ info.userid);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
+ * Allow an INotificationListener to request the list of outstanding notifications seen by
+ * the current user. Useful when starting up, after which point the listener callbacks
+ * should be used.
+ *
+ * @param token The binder for the listener, to check that the caller is allowed
+ */
+ @Override
+ public StatusBarNotification[] getActiveNotificationsFromListener(
+ INotificationListener token) {
+ NotificationListenerInfo info = checkListenerToken(token);
+
+ StatusBarNotification[] result = new StatusBarNotification[0];
+ ArrayList<StatusBarNotification> list = new ArrayList<StatusBarNotification>();
+ synchronized (mNotificationList) {
+ final int N = mNotificationList.size();
+ for (int i=0; i<N; i++) {
+ StatusBarNotification sbn = mNotificationList.get(i).sbn;
+ if (info.enabledAndUserMatches(sbn)) {
+ list.add(sbn);
+ }
+ }
+ }
+ return list.toArray(result);
+ }
+
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+ != PackageManager.PERMISSION_GRANTED) {
+ pw.println("Permission Denial: can't dump NotificationManager from from pid="
+ + Binder.getCallingPid()
+ + ", uid=" + Binder.getCallingUid());
+ return;
+ }
+
+ dumpImpl(pw);
+ }
+ };
+
+ void dumpImpl(PrintWriter pw) {
+ pw.println("Current Notification Manager state:");
+
+ pw.println(" Listeners (" + mEnabledListenersForCurrentUser.size()
+ + ") enabled for current user:");
+ for (ComponentName cmpt : mEnabledListenersForCurrentUser) {
+ pw.println(" " + cmpt);
+ }
+
+ pw.println(" Live listeners (" + mListeners.size() + "):");
+ for (NotificationListenerInfo info : mListeners) {
+ pw.println(" " + info.component
+ + " (user " + info.userid + "): " + info.listener
+ + (info.isSystem?" SYSTEM":""));
+ }
+
+ int N;
+
+ synchronized (mToastQueue) {
+ N = mToastQueue.size();
+ if (N > 0) {
+ pw.println(" Toast Queue:");
+ for (int i=0; i<N; i++) {
+ mToastQueue.get(i).dump(pw, " ");
+ }
+ pw.println(" ");
+ }
+
+ }
+
+ synchronized (mNotificationList) {
+ N = mNotificationList.size();
+ if (N > 0) {
+ pw.println(" Notification List:");
+ for (int i=0; i<N; i++) {
+ mNotificationList.get(i).dump(pw, " ", getContext());
+ }
+ pw.println(" ");
+ }
+
+ N = mLights.size();
+ if (N > 0) {
+ pw.println(" Lights List:");
+ for (int i=0; i<N; i++) {
+ pw.println(" " + mLights.get(i));
+ }
+ pw.println(" ");
+ }
+
+ pw.println(" mSoundNotification=" + mSoundNotification);
+ pw.println(" mVibrateNotification=" + mVibrateNotification);
+ pw.println(" mDisabledNotifications=0x"
+ + Integer.toHexString(mDisabledNotifications));
+ pw.println(" mSystemReady=" + mSystemReady);
+ pw.println(" mArchive=" + mArchive.toString());
+ Iterator<StatusBarNotification> iter = mArchive.descendingIterator();
+ int i=0;
+ while (iter.hasNext()) {
+ pw.println(" " + iter.next());
+ if (++i >= 5) {
+ if (iter.hasNext()) pw.println(" ...");
+ break;
+ }
+ }
+
}
}
+ /**
+ * The private API only accessible to the system process.
+ */
+ private final NotificationManagerInternal mInternalService = new NotificationManagerInternal() {
+ @Override
+ public void enqueueNotification(String pkg, String basePkg, int callingUid, int callingPid,
+ String tag, int id, Notification notification, int[] idReceived, int userId) {
+ enqueueNotificationInternal(pkg, basePkg, callingUid, callingPid, tag, id, notification,
+ idReceived, userId);
+ }
+ };
- // Notifications
- // ============================================================================
- public void enqueueNotificationWithTag(String pkg, String basePkg, String tag, int id,
- Notification notification, int[] idOut, int userId)
- {
- enqueueNotificationInternal(pkg, basePkg, Binder.getCallingUid(), Binder.getCallingPid(),
- tag, id, notification, idOut, userId);
- }
-
- private final static int clamp(int x, int low, int high) {
- return (x < low) ? low : ((x > high) ? high : x);
- }
-
- // Not exposed via Binder; for system use only (otherwise malicious apps could spoof the
- // uid/pid of another application)
-
- public void enqueueNotificationInternal(final String pkg, String basePkg, final int callingUid,
+ void enqueueNotificationInternal(final String pkg, String basePkg, final int callingUid,
final int callingPid, final String tag, final int id, final Notification notification,
- int[] idOut, int incomingUserId)
- {
+ int[] idOut, int incomingUserId) {
if (DBG) {
- Slog.v(TAG, "enqueueNotificationInternal: pkg=" + pkg + " id=" + id + " notification=" + notification);
+ Slog.v(TAG, "enqueueNotificationInternal: pkg=" + pkg + " id=" + id
+ + " notification=" + notification);
}
checkCallerIsSystemOrSameApp(pkg);
final boolean isSystemNotification = isUidSystem(callingUid) || ("android".equals(pkg));
@@ -1787,23 +1794,21 @@
if (notification.icon != 0) {
if (old != null && old.statusBarKey != null) {
r.statusBarKey = old.statusBarKey;
- long identity = Binder.clearCallingIdentity();
+ final long identity = Binder.clearCallingIdentity();
try {
mStatusBar.updateNotification(r.statusBarKey, n);
- }
- finally {
+ } finally {
Binder.restoreCallingIdentity(identity);
}
} else {
- long identity = Binder.clearCallingIdentity();
+ final long identity = Binder.clearCallingIdentity();
try {
r.statusBarKey = mStatusBar.addNotification(n);
if ((n.getNotification().flags & Notification.FLAG_SHOW_LIGHTS) != 0
&& canInterrupt) {
mAttentionLight.pulse();
}
- }
- finally {
+ } finally {
Binder.restoreCallingIdentity(identity);
}
}
@@ -1816,33 +1821,32 @@
} else {
Slog.e(TAG, "Not posting notification with icon==0: " + notification);
if (old != null && old.statusBarKey != null) {
- long identity = Binder.clearCallingIdentity();
+ final long identity = Binder.clearCallingIdentity();
try {
mStatusBar.removeNotification(old.statusBarKey);
- }
- finally {
+ } finally {
Binder.restoreCallingIdentity(identity);
}
notifyRemovedLocked(r);
}
// ATTENTION: in a future release we will bail out here
- // so that we do not play sounds, show lights, etc. for invalid notifications
+ // so that we do not play sounds, show lights, etc. for invalid
+ // notifications
Slog.e(TAG, "WARNING: In a future release this will crash the app: "
+ n.getPackageName());
}
// If we're not supposed to beep, vibrate, etc. then don't.
- if (((mDisabledNotifications & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) == 0)
+ if (((mDisabledNotifications
+ & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) == 0)
&& (!(old != null
&& (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0 ))
&& (r.getUserId() == UserHandle.USER_ALL ||
(r.getUserId() == userId && r.getUserId() == currentUser))
&& canInterrupt
- && mSystemReady) {
-
- final AudioManager audioManager = (AudioManager) mContext
- .getSystemService(Context.AUDIO_SERVICE);
+ && mSystemReady
+ && mAudioManager != null) {
// sound
@@ -1861,7 +1865,7 @@
soundUri = Settings.System.DEFAULT_NOTIFICATION_URI;
// check to see if the default notification sound is silent
- ContentResolver resolver = mContext.getContentResolver();
+ ContentResolver resolver = getContext().getContentResolver();
hasValidSound = Settings.System.getString(resolver,
Settings.System.NOTIFICATION_SOUND) != null;
} else if (notification.sound != null) {
@@ -1870,7 +1874,8 @@
}
if (hasValidSound) {
- boolean looping = (notification.flags & Notification.FLAG_INSISTENT) != 0;
+ boolean looping =
+ (notification.flags & Notification.FLAG_INSISTENT) != 0;
int audioStreamType;
if (notification.audioStreamType >= 0) {
audioStreamType = notification.audioStreamType;
@@ -1880,11 +1885,12 @@
mSoundNotification = r;
// do not play notifications if stream volume is 0 (typically because
// ringer mode is silent) or if there is a user of exclusive audio focus
- if ((audioManager.getStreamVolume(audioStreamType) != 0)
- && !audioManager.isAudioFocusExclusive()) {
+ if ((mAudioManager.getStreamVolume(audioStreamType) != 0)
+ && !mAudioManager.isAudioFocusExclusive()) {
final long identity = Binder.clearCallingIdentity();
try {
- final IRingtonePlayer player = mAudioService.getRingtonePlayer();
+ final IRingtonePlayer player =
+ mAudioManager.getRingtonePlayer();
if (player != null) {
player.playAsync(soundUri, user, looping, audioStreamType);
}
@@ -1904,7 +1910,7 @@
final boolean convertSoundToVibration =
!hasCustomVibrate
&& hasValidSound
- && (audioManager.getRingerMode()
+ && (mAudioManager.getRingerMode()
== AudioManager.RINGER_MODE_VIBRATE);
// The DEFAULT_VIBRATE flag trumps any custom vibration AND the fallback.
@@ -1912,7 +1918,7 @@
(notification.defaults & Notification.DEFAULT_VIBRATE) != 0;
if ((useDefaultVibrate || convertSoundToVibration || hasCustomVibrate)
- && !(audioManager.getRingerMode()
+ && !(mAudioManager.getRingerMode()
== AudioManager.RINGER_MODE_SILENT)) {
mVibrateNotification = r;
@@ -1966,8 +1972,158 @@
idOut[0] = id;
}
- private void sendAccessibilityEvent(Notification notification, CharSequence packageName) {
- AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
+ void registerListenerImpl(final INotificationListener listener,
+ final ComponentName component, final int userid) {
+ synchronized (mNotificationList) {
+ try {
+ NotificationListenerInfo info
+ = new NotificationListenerInfo(listener, component, userid, true);
+ listener.asBinder().linkToDeath(info, 0);
+ mListeners.add(info);
+ } catch (RemoteException e) {
+ // already dead
+ }
+ }
+ }
+
+ void unregisterListenerImpl(final INotificationListener listener, final int userid) {
+ synchronized (mNotificationList) {
+ final int N = mListeners.size();
+ for (int i=N-1; i>=0; i--) {
+ final NotificationListenerInfo info = mListeners.get(i);
+ if (info.listener.asBinder() == listener.asBinder()
+ && info.userid == userid) {
+ mListeners.remove(i);
+ if (info.connection != null) {
+ getContext().unbindService(info.connection);
+ }
+ }
+ }
+ }
+ }
+
+ void showNextToastLocked() {
+ ToastRecord record = mToastQueue.get(0);
+ while (record != null) {
+ if (DBG) Slog.d(TAG, "Show pkg=" + record.pkg + " callback=" + record.callback);
+ try {
+ record.callback.show();
+ scheduleTimeoutLocked(record);
+ return;
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Object died trying to show notification " + record.callback
+ + " in package " + record.pkg);
+ // remove it from the list and let the process die
+ int index = mToastQueue.indexOf(record);
+ if (index >= 0) {
+ mToastQueue.remove(index);
+ }
+ keepProcessAliveLocked(record.pid);
+ if (mToastQueue.size() > 0) {
+ record = mToastQueue.get(0);
+ } else {
+ record = null;
+ }
+ }
+ }
+ }
+
+ void cancelToastLocked(int index) {
+ ToastRecord record = mToastQueue.get(index);
+ try {
+ record.callback.hide();
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Object died trying to hide notification " + record.callback
+ + " in package " + record.pkg);
+ // don't worry about this, we're about to remove it from
+ // the list anyway
+ }
+ mToastQueue.remove(index);
+ keepProcessAliveLocked(record.pid);
+ if (mToastQueue.size() > 0) {
+ // Show the next one. If the callback fails, this will remove
+ // it from the list, so don't assume that the list hasn't changed
+ // after this point.
+ showNextToastLocked();
+ }
+ }
+
+ private void scheduleTimeoutLocked(ToastRecord r)
+ {
+ mHandler.removeCallbacksAndMessages(r);
+ Message m = Message.obtain(mHandler, MESSAGE_TIMEOUT, r);
+ long delay = r.duration == Toast.LENGTH_LONG ? LONG_DELAY : SHORT_DELAY;
+ mHandler.sendMessageDelayed(m, delay);
+ }
+
+ private void handleTimeout(ToastRecord record)
+ {
+ if (DBG) Slog.d(TAG, "Timeout pkg=" + record.pkg + " callback=" + record.callback);
+ synchronized (mToastQueue) {
+ int index = indexOfToastLocked(record.pkg, record.callback);
+ if (index >= 0) {
+ cancelToastLocked(index);
+ }
+ }
+ }
+
+ // lock on mToastQueue
+ int indexOfToastLocked(String pkg, ITransientNotification callback)
+ {
+ IBinder cbak = callback.asBinder();
+ ArrayList<ToastRecord> list = mToastQueue;
+ int len = list.size();
+ for (int i=0; i<len; i++) {
+ ToastRecord r = list.get(i);
+ if (r.pkg.equals(pkg) && r.callback.asBinder() == cbak) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ // lock on mToastQueue
+ void keepProcessAliveLocked(int pid)
+ {
+ int toastCount = 0; // toasts from this pid
+ ArrayList<ToastRecord> list = mToastQueue;
+ int N = list.size();
+ for (int i=0; i<N; i++) {
+ ToastRecord r = list.get(i);
+ if (r.pid == pid) {
+ toastCount++;
+ }
+ }
+ try {
+ mAm.setProcessForeground(mForegroundToken, pid, toastCount > 0);
+ } catch (RemoteException e) {
+ // Shouldn't happen.
+ }
+ }
+
+ private final class WorkerHandler extends Handler
+ {
+ @Override
+ public void handleMessage(Message msg)
+ {
+ switch (msg.what)
+ {
+ case MESSAGE_TIMEOUT:
+ handleTimeout((ToastRecord)msg.obj);
+ break;
+ }
+ }
+ }
+
+
+ // Notifications
+ // ============================================================================
+ static int clamp(int x, int low, int high) {
+ return (x < low) ? low : ((x > high) ? high : x);
+ }
+
+ void sendAccessibilityEvent(Notification notification, CharSequence packageName) {
+ AccessibilityManager manager = AccessibilityManager.getInstance(getContext());
if (!manager.isEnabled()) {
return;
}
@@ -2001,11 +2157,10 @@
// status bar
if (r.getNotification().icon != 0) {
- long identity = Binder.clearCallingIdentity();
+ final long identity = Binder.clearCallingIdentity();
try {
mStatusBar.removeNotification(r.statusBarKey);
- }
- finally {
+ } finally {
Binder.restoreCallingIdentity(identity);
}
r.statusBarKey = null;
@@ -2017,7 +2172,7 @@
mSoundNotification = null;
final long identity = Binder.clearCallingIdentity();
try {
- final IRingtonePlayer player = mAudioService.getRingtonePlayer();
+ final IRingtonePlayer player = mAudioManager.getRingtonePlayer();
if (player != null) {
player.stopAsync();
}
@@ -2053,7 +2208,7 @@
* Cancels a notification ONLY if it has all of the {@code mustHaveFlags}
* and none of the {@code mustNotHaveFlags}.
*/
- private void cancelNotification(final String pkg, final String tag, final int id,
+ void cancelNotification(final String pkg, final String tag, final int id,
final int mustHaveFlags, final int mustNotHaveFlags, final boolean sendDelete,
final int userId) {
// In enqueueNotificationInternal notifications are added by scheduling the
@@ -2146,26 +2301,7 @@
}
}
- public void cancelNotificationWithTag(String pkg, String tag, int id, int userId) {
- checkCallerIsSystemOrSameApp(pkg);
- userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
- Binder.getCallingUid(), userId, true, false, "cancelNotificationWithTag", pkg);
- // Don't allow client applications to cancel foreground service notis.
- cancelNotification(pkg, tag, id, 0,
- Binder.getCallingUid() == Process.SYSTEM_UID
- ? 0 : Notification.FLAG_FOREGROUND_SERVICE, false, userId);
- }
- public void cancelAllNotifications(String pkg, int userId) {
- checkCallerIsSystemOrSameApp(pkg);
-
- userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
- Binder.getCallingUid(), userId, true, false, "cancelAllNotifications", pkg);
-
- // Calling from user space, don't allow the canceling of actively
- // running foreground services.
- cancelAllNotificationsInt(pkg, 0, Notification.FLAG_FOREGROUND_SERVICE, true, userId);
- }
// Return true if the UID is a system or phone UID and therefore should not have
// any notifications or toasts blocked.
@@ -2225,7 +2361,7 @@
}
// lock on mNotificationList
- private void updateLightsLocked()
+ void updateLightsLocked()
{
// handle notification lights
if (mLedNotification == null) {
@@ -2251,14 +2387,14 @@
}
if (mNotificationPulseEnabled) {
// pulse repeatedly
- mNotificationLight.setFlashing(ledARGB, LightsService.LIGHT_FLASH_TIMED,
+ mNotificationLight.setFlashing(ledARGB, Light.LIGHT_FLASH_TIMED,
ledOnMS, ledOffMS);
}
}
}
// lock on mNotificationList
- private int indexOfNotificationLocked(String pkg, String tag, int id, int userId)
+ int indexOfNotificationLocked(String pkg, String tag, int id, int userId)
{
ArrayList<NotificationRecord> list = mNotificationList;
final int len = list.size();
@@ -2288,81 +2424,4 @@
updateLightsLocked();
}
}
-
- // ======================================================================
- @Override
- protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump NotificationManager from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
-
- pw.println("Current Notification Manager state:");
-
- pw.println(" Listeners (" + mEnabledListenersForCurrentUser.size()
- + ") enabled for current user:");
- for (ComponentName cmpt : mEnabledListenersForCurrentUser) {
- pw.println(" " + cmpt);
- }
-
- pw.println(" Live listeners (" + mListeners.size() + "):");
- for (NotificationListenerInfo info : mListeners) {
- pw.println(" " + info.component
- + " (user " + info.userid + "): " + info.listener
- + (info.isSystem?" SYSTEM":""));
- }
-
- int N;
-
- synchronized (mToastQueue) {
- N = mToastQueue.size();
- if (N > 0) {
- pw.println(" Toast Queue:");
- for (int i=0; i<N; i++) {
- mToastQueue.get(i).dump(pw, " ");
- }
- pw.println(" ");
- }
-
- }
-
- synchronized (mNotificationList) {
- N = mNotificationList.size();
- if (N > 0) {
- pw.println(" Notification List:");
- for (int i=0; i<N; i++) {
- mNotificationList.get(i).dump(pw, " ", mContext);
- }
- pw.println(" ");
- }
-
- N = mLights.size();
- if (N > 0) {
- pw.println(" Lights List:");
- for (int i=0; i<N; i++) {
- pw.println(" " + mLights.get(i));
- }
- pw.println(" ");
- }
-
- pw.println(" mSoundNotification=" + mSoundNotification);
- pw.println(" mVibrateNotification=" + mVibrateNotification);
- pw.println(" mDisabledNotifications=0x" + Integer.toHexString(mDisabledNotifications));
- pw.println(" mSystemReady=" + mSystemReady);
- pw.println(" mArchive=" + mArchive.toString());
- Iterator<StatusBarNotification> iter = mArchive.descendingIterator();
- int i=0;
- while (iter.hasNext()) {
- pw.println(" " + iter.next());
- if (++i >= 5) {
- if (iter.hasNext()) pw.println(" ...");
- break;
- }
- }
-
- }
- }
}
diff --git a/services/java/com/android/server/os/SchedulingPolicyService.java b/services/core/java/com/android/server/os/SchedulingPolicyService.java
similarity index 100%
rename from services/java/com/android/server/os/SchedulingPolicyService.java
rename to services/core/java/com/android/server/os/SchedulingPolicyService.java
diff --git a/services/java/com/android/server/pm/BasePermission.java b/services/core/java/com/android/server/pm/BasePermission.java
similarity index 100%
rename from services/java/com/android/server/pm/BasePermission.java
rename to services/core/java/com/android/server/pm/BasePermission.java
diff --git a/services/java/com/android/server/pm/GrantedPermissions.java b/services/core/java/com/android/server/pm/GrantedPermissions.java
similarity index 100%
rename from services/java/com/android/server/pm/GrantedPermissions.java
rename to services/core/java/com/android/server/pm/GrantedPermissions.java
diff --git a/services/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
similarity index 97%
rename from services/java/com/android/server/pm/Installer.java
rename to services/core/java/com/android/server/pm/Installer.java
index 0d2b503..e2ff146 100644
--- a/services/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -16,6 +16,8 @@
package com.android.server.pm;
+import com.android.server.SystemService;
+
import android.content.pm.PackageStats;
import android.net.LocalSocket;
import android.net.LocalSocketAddress;
@@ -25,21 +27,24 @@
import java.io.InputStream;
import java.io.OutputStream;
-public final class Installer {
+public final class Installer extends SystemService {
private static final String TAG = "Installer";
private static final boolean LOCAL_DEBUG = false;
InputStream mIn;
-
OutputStream mOut;
-
LocalSocket mSocket;
byte buf[] = new byte[1024];
-
int buflen = 0;
+ @Override
+ public void onStart() {
+ Slog.i(TAG, "Waiting for installd to be ready.");
+ ping();
+ }
+
private boolean connect() {
if (mSocket != null) {
return true;
diff --git a/services/java/com/android/server/pm/KeySetManager.java b/services/core/java/com/android/server/pm/KeySetManager.java
similarity index 100%
rename from services/java/com/android/server/pm/KeySetManager.java
rename to services/core/java/com/android/server/pm/KeySetManager.java
diff --git a/services/java/com/android/server/pm/PackageKeySetData.java b/services/core/java/com/android/server/pm/PackageKeySetData.java
similarity index 100%
rename from services/java/com/android/server/pm/PackageKeySetData.java
rename to services/core/java/com/android/server/pm/PackageKeySetData.java
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
similarity index 99%
rename from services/java/com/android/server/pm/PackageManagerService.java
rename to services/core/java/com/android/server/pm/PackageManagerService.java
index 7e244b9..df83fd7 100755
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -38,10 +38,11 @@
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.XmlUtils;
-import com.android.server.DeviceStorageMonitorService;
import com.android.server.EventLogTags;
import com.android.server.IntentResolver;
+import com.android.server.ServiceThread;
+import com.android.server.LocalServices;
import com.android.server.Watchdog;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -92,6 +93,7 @@
import android.content.pm.VerifierDeviceIdentity;
import android.content.pm.VerifierInfo;
import android.content.res.Resources;
+import android.hardware.display.DisplayManager;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
@@ -127,7 +129,6 @@
import android.util.SparseArray;
import android.util.Xml;
import android.view.Display;
-import android.view.WindowManager;
import java.io.BufferedOutputStream;
import java.io.File;
@@ -162,6 +163,7 @@
import libcore.io.StructStat;
import com.android.internal.R;
+import com.android.server.storage.DeviceStorageMonitorInternal;
/**
* Keep track of all those .apks everywhere.
@@ -259,8 +261,7 @@
static final String mTempContainerPrefix = "smdl2tmp";
- final HandlerThread mHandlerThread = new HandlerThread("PackageManager",
- Process.THREAD_PRIORITY_BACKGROUND);
+ final ServiceThread mHandlerThread;
final PackageHandler mHandler;
final int mSdkVersion = Build.VERSION.SDK_INT;
@@ -1067,6 +1068,12 @@
return res;
}
+ private static void getDefaultDisplayMetrics(Context context, DisplayMetrics metrics) {
+ DisplayManager displayManager = (DisplayManager) context.getSystemService(
+ Context.DISPLAY_SERVICE);
+ displayManager.getDisplay(Display.DEFAULT_DISPLAY).getMetrics(metrics);
+ }
+
public PackageManagerService(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
@@ -1114,17 +1121,16 @@
mInstaller = installer;
- WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
- Display d = wm.getDefaultDisplay();
- d.getMetrics(mMetrics);
+ getDefaultDisplayMetrics(context, mMetrics);
synchronized (mInstallLock) {
// writer
synchronized (mPackages) {
+ mHandlerThread = new ServiceThread(TAG,
+ Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
mHandlerThread.start();
mHandler = new PackageHandler(mHandlerThread.getLooper());
- Watchdog.getInstance().addThread(mHandler, mHandlerThread.getName(),
- WATCHDOG_TIMEOUT);
+ Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);
File dataDir = Environment.getDataDirectory();
mAppDataDir = new File(dataDir, "data");
@@ -7345,6 +7351,15 @@
return pkgLite.recommendedInstallLocation;
}
+ private long getMemoryLowThreshold() {
+ final DeviceStorageMonitorInternal
+ dsm = LocalServices.getService(DeviceStorageMonitorInternal.class);
+ if (dsm == null) {
+ return 0L;
+ }
+ return dsm.getMemoryLowThreshold();
+ }
+
/*
* Invoke remote method to get package information and install
* location values. Override install location based on default
@@ -7362,15 +7377,9 @@
Slog.w(TAG, "Conflicting flags specified for installing on both internal and external");
ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
} else {
- final long lowThreshold;
-
- final DeviceStorageMonitorService dsm = (DeviceStorageMonitorService) ServiceManager
- .getService(DeviceStorageMonitorService.SERVICE);
- if (dsm == null) {
+ final long lowThreshold = getMemoryLowThreshold();
+ if (lowThreshold == 0L) {
Log.w(TAG, "Couldn't get low memory threshold; no free limit imposed");
- lowThreshold = 0L;
- } else {
- lowThreshold = dsm.getMemoryLowThreshold();
}
try {
@@ -7928,8 +7937,8 @@
boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
final long lowThreshold;
- final DeviceStorageMonitorService dsm = (DeviceStorageMonitorService) ServiceManager
- .getService(DeviceStorageMonitorService.SERVICE);
+ final DeviceStorageMonitorInternal
+ dsm = LocalServices.getService(DeviceStorageMonitorInternal.class);
if (dsm == null) {
Log.w(TAG, "Couldn't get low memory threshold; no free limit imposed");
lowThreshold = 0L;
@@ -9744,10 +9753,10 @@
clearExternalStorageDataSync(packageName, userId, true);
if (succeeded) {
// invoke DeviceStorageMonitor's update method to clear any notifications
- DeviceStorageMonitorService dsm = (DeviceStorageMonitorService)
- ServiceManager.getService(DeviceStorageMonitorService.SERVICE);
+ DeviceStorageMonitorInternal
+ dsm = LocalServices.getService(DeviceStorageMonitorInternal.class);
if (dsm != null) {
- dsm.updateMemory();
+ dsm.checkMemory();
}
}
if(observer != null) {
@@ -11572,12 +11581,17 @@
return true;
}
+ @Override
public boolean isStorageLow() {
final long token = Binder.clearCallingIdentity();
try {
- final DeviceStorageMonitorService dsm = (DeviceStorageMonitorService) ServiceManager
- .getService(DeviceStorageMonitorService.SERVICE);
- return dsm.isMemoryLow();
+ final DeviceStorageMonitorInternal
+ dsm = LocalServices.getService(DeviceStorageMonitorInternal.class);
+ if (dsm != null) {
+ return dsm.isMemoryLow();
+ } else {
+ return false;
+ }
} finally {
Binder.restoreCallingIdentity(token);
}
diff --git a/services/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
similarity index 100%
rename from services/java/com/android/server/pm/PackageSetting.java
rename to services/core/java/com/android/server/pm/PackageSetting.java
diff --git a/services/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
similarity index 100%
rename from services/java/com/android/server/pm/PackageSettingBase.java
rename to services/core/java/com/android/server/pm/PackageSettingBase.java
diff --git a/services/java/com/android/server/pm/PackageSignatures.java b/services/core/java/com/android/server/pm/PackageSignatures.java
similarity index 100%
rename from services/java/com/android/server/pm/PackageSignatures.java
rename to services/core/java/com/android/server/pm/PackageSignatures.java
diff --git a/services/java/com/android/server/pm/PackageVerificationResponse.java b/services/core/java/com/android/server/pm/PackageVerificationResponse.java
similarity index 100%
rename from services/java/com/android/server/pm/PackageVerificationResponse.java
rename to services/core/java/com/android/server/pm/PackageVerificationResponse.java
diff --git a/services/java/com/android/server/pm/PackageVerificationState.java b/services/core/java/com/android/server/pm/PackageVerificationState.java
similarity index 100%
rename from services/java/com/android/server/pm/PackageVerificationState.java
rename to services/core/java/com/android/server/pm/PackageVerificationState.java
diff --git a/services/java/com/android/server/pm/PendingPackage.java b/services/core/java/com/android/server/pm/PendingPackage.java
similarity index 100%
rename from services/java/com/android/server/pm/PendingPackage.java
rename to services/core/java/com/android/server/pm/PendingPackage.java
diff --git a/services/java/com/android/server/pm/PreferredActivity.java b/services/core/java/com/android/server/pm/PreferredActivity.java
similarity index 98%
rename from services/java/com/android/server/pm/PreferredActivity.java
rename to services/core/java/com/android/server/pm/PreferredActivity.java
index f93ba2f..8916926 100644
--- a/services/java/com/android/server/pm/PreferredActivity.java
+++ b/services/core/java/com/android/server/pm/PreferredActivity.java
@@ -17,7 +17,6 @@
package com.android.server.pm;
import com.android.internal.util.XmlUtils;
-import com.android.server.PreferredComponent;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
diff --git a/services/java/com/android/server/PreferredComponent.java b/services/core/java/com/android/server/pm/PreferredComponent.java
similarity index 99%
rename from services/java/com/android/server/PreferredComponent.java
rename to services/core/java/com/android/server/pm/PreferredComponent.java
index a7af252..f437372 100644
--- a/services/java/com/android/server/PreferredComponent.java
+++ b/services/core/java/com/android/server/pm/PreferredComponent.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server;
+package com.android.server.pm;
import com.android.internal.util.XmlUtils;
diff --git a/services/java/com/android/server/pm/PreferredIntentResolver.java b/services/core/java/com/android/server/pm/PreferredIntentResolver.java
similarity index 100%
rename from services/java/com/android/server/pm/PreferredIntentResolver.java
rename to services/core/java/com/android/server/pm/PreferredIntentResolver.java
diff --git a/services/java/com/android/server/pm/SELinuxMMAC.java b/services/core/java/com/android/server/pm/SELinuxMMAC.java
similarity index 100%
rename from services/java/com/android/server/pm/SELinuxMMAC.java
rename to services/core/java/com/android/server/pm/SELinuxMMAC.java
diff --git a/services/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
similarity index 100%
rename from services/java/com/android/server/pm/Settings.java
rename to services/core/java/com/android/server/pm/Settings.java
diff --git a/services/java/com/android/server/pm/SharedUserSetting.java b/services/core/java/com/android/server/pm/SharedUserSetting.java
similarity index 100%
rename from services/java/com/android/server/pm/SharedUserSetting.java
rename to services/core/java/com/android/server/pm/SharedUserSetting.java
diff --git a/services/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
similarity index 100%
rename from services/java/com/android/server/pm/UserManagerService.java
rename to services/core/java/com/android/server/pm/UserManagerService.java
diff --git a/services/java/com/android/server/power/DisplayBlanker.java b/services/core/java/com/android/server/power/DisplayBlanker.java
similarity index 100%
rename from services/java/com/android/server/power/DisplayBlanker.java
rename to services/core/java/com/android/server/power/DisplayBlanker.java
diff --git a/services/java/com/android/server/power/DisplayPowerController.java b/services/core/java/com/android/server/power/DisplayPowerController.java
similarity index 98%
rename from services/java/com/android/server/power/DisplayPowerController.java
rename to services/core/java/com/android/server/power/DisplayPowerController.java
index 60d44c7..f1be504 100644
--- a/services/java/com/android/server/power/DisplayPowerController.java
+++ b/services/core/java/com/android/server/power/DisplayPowerController.java
@@ -16,10 +16,10 @@
package com.android.server.power;
-import com.android.server.LightsService;
-import com.android.server.TwilightService;
-import com.android.server.TwilightService.TwilightState;
-import com.android.server.display.DisplayManagerService;
+import com.android.server.lights.LightsManager;
+import com.android.server.twilight.TwilightListener;
+import com.android.server.twilight.TwilightManager;
+import com.android.server.twilight.TwilightState;
import android.animation.Animator;
import android.animation.ObjectAnimator;
@@ -179,13 +179,10 @@
private Handler mCallbackHandler;
// The lights service.
- private final LightsService mLights;
+ private final LightsManager mLights;
// The twilight service.
- private final TwilightService mTwilight;
-
- // The display manager.
- private final DisplayManagerService mDisplayManager;
+ private final TwilightManager mTwilight;
// The sensor manager.
private final SensorManager mSensorManager;
@@ -351,8 +348,7 @@
* Creates the display power controller.
*/
public DisplayPowerController(Looper looper, Context context, Notifier notifier,
- LightsService lights, TwilightService twilight, SensorManager sensorManager,
- DisplayManagerService displayManager,
+ LightsManager lights, TwilightManager twilight, SensorManager sensorManager,
SuspendBlocker displaySuspendBlocker, DisplayBlanker displayBlanker,
Callbacks callbacks, Handler callbackHandler) {
mHandler = new DisplayControllerHandler(looper);
@@ -365,7 +361,6 @@
mLights = lights;
mTwilight = twilight;
mSensorManager = sensorManager;
- mDisplayManager = displayManager;
final Resources resources = context.getResources();
@@ -526,9 +521,8 @@
}
private void initialize() {
- mPowerState = new DisplayPowerState(
- new ElectronBeam(mDisplayManager), mDisplayBlanker,
- mLights.getLight(LightsService.LIGHT_ID_BACKLIGHT));
+ mPowerState = new DisplayPowerState(new ElectronBeam(), mDisplayBlanker,
+ mLights.getLight(LightsManager.LIGHT_ID_BACKLIGHT));
mElectronBeamOnAnimator = ObjectAnimator.ofFloat(
mPowerState, DisplayPowerState.ELECTRON_BEAM_LEVEL, 0.0f, 1.0f);
@@ -1368,8 +1362,7 @@
}
};
- private final TwilightService.TwilightListener mTwilightListener =
- new TwilightService.TwilightListener() {
+ private final TwilightListener mTwilightListener = new TwilightListener() {
@Override
public void onTwilightStateChanged() {
mTwilightChanged = true;
diff --git a/services/java/com/android/server/power/DisplayPowerRequest.java b/services/core/java/com/android/server/power/DisplayPowerRequest.java
similarity index 100%
rename from services/java/com/android/server/power/DisplayPowerRequest.java
rename to services/core/java/com/android/server/power/DisplayPowerRequest.java
diff --git a/services/java/com/android/server/power/DisplayPowerState.java b/services/core/java/com/android/server/power/DisplayPowerState.java
similarity index 98%
rename from services/java/com/android/server/power/DisplayPowerState.java
rename to services/core/java/com/android/server/power/DisplayPowerState.java
index fa318f8..42af4b4 100644
--- a/services/java/com/android/server/power/DisplayPowerState.java
+++ b/services/core/java/com/android/server/power/DisplayPowerState.java
@@ -16,7 +16,7 @@
package com.android.server.power;
-import com.android.server.LightsService;
+import com.android.server.lights.Light;
import android.os.AsyncTask;
import android.os.Handler;
@@ -56,7 +56,7 @@
private final Choreographer mChoreographer;
private final ElectronBeam mElectronBeam;
private final DisplayBlanker mDisplayBlanker;
- private final LightsService.Light mBacklight;
+ private final Light mBacklight;
private final PhotonicModulator mPhotonicModulator;
private boolean mScreenOn;
@@ -72,7 +72,7 @@
private Runnable mCleanListener;
public DisplayPowerState(ElectronBeam electronBean,
- DisplayBlanker displayBlanker, LightsService.Light backlight) {
+ DisplayBlanker displayBlanker, Light backlight) {
mHandler = new Handler(true /*async*/);
mChoreographer = Choreographer.getInstance();
mElectronBeam = electronBean;
diff --git a/services/java/com/android/server/power/ElectronBeam.java b/services/core/java/com/android/server/power/ElectronBeam.java
similarity index 95%
rename from services/java/com/android/server/power/ElectronBeam.java
rename to services/core/java/com/android/server/power/ElectronBeam.java
index 729bd16..64921d7 100644
--- a/services/java/com/android/server/power/ElectronBeam.java
+++ b/services/core/java/com/android/server/power/ElectronBeam.java
@@ -23,6 +23,8 @@
import android.graphics.PixelFormat;
import android.graphics.SurfaceTexture;
+import android.hardware.display.DisplayManagerInternal;
+import android.hardware.display.DisplayManagerInternal.DisplayTransactionListener;
import android.opengl.EGL14;
import android.opengl.EGLConfig;
import android.opengl.EGLContext;
@@ -40,8 +42,7 @@
import android.view.SurfaceControl;
import android.view.SurfaceSession;
-import com.android.server.display.DisplayManagerService;
-import com.android.server.display.DisplayTransactionListener;
+import com.android.server.LocalServices;
/**
* Bzzzoooop! *crackle*
@@ -77,7 +78,7 @@
private boolean mPrepared;
private int mMode;
- private final DisplayManagerService mDisplayManager;
+ private final DisplayManagerInternal mDisplayManagerInternal;
private int mDisplayLayerStack; // layer stack associated with primary display
private int mDisplayWidth; // real width, not rotated
private int mDisplayHeight; // real height, not rotated
@@ -118,8 +119,8 @@
public static final int MODE_FADE = 2;
- public ElectronBeam(DisplayManagerService displayManager) {
- mDisplayManager = displayManager;
+ public ElectronBeam() {
+ mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
}
/**
@@ -138,7 +139,7 @@
// Get the display size and layer stack.
// This is not expected to change while the electron beam surface is showing.
- DisplayInfo displayInfo = mDisplayManager.getDisplayInfo(Display.DEFAULT_DISPLAY);
+ DisplayInfo displayInfo = mDisplayManagerInternal.getDisplayInfo(Display.DEFAULT_DISPLAY);
mDisplayLayerStack = displayInfo.layerStack;
mDisplayWidth = displayInfo.getNaturalWidth();
mDisplayHeight = displayInfo.getNaturalHeight();
@@ -527,7 +528,7 @@
mSurface = new Surface();
mSurface.copyFrom(mSurfaceControl);
- mSurfaceLayout = new NaturalSurfaceLayout(mDisplayManager, mSurfaceControl);
+ mSurfaceLayout = new NaturalSurfaceLayout(mDisplayManagerInternal, mSurfaceControl);
mSurfaceLayout.onDisplayTransaction();
} finally {
SurfaceControl.closeTransaction();
@@ -685,20 +686,21 @@
* owns the electron beam.
*/
private static final class NaturalSurfaceLayout implements DisplayTransactionListener {
- private final DisplayManagerService mDisplayManager;
+ private final DisplayManagerInternal mDisplayManagerInternal;
private SurfaceControl mSurfaceControl;
- public NaturalSurfaceLayout(DisplayManagerService displayManager, SurfaceControl surfaceControl) {
- mDisplayManager = displayManager;
+ public NaturalSurfaceLayout(DisplayManagerInternal displayManagerInternal,
+ SurfaceControl surfaceControl) {
+ mDisplayManagerInternal = displayManagerInternal;
mSurfaceControl = surfaceControl;
- mDisplayManager.registerDisplayTransactionListener(this);
+ mDisplayManagerInternal.registerDisplayTransactionListener(this);
}
public void dispose() {
synchronized (this) {
mSurfaceControl = null;
}
- mDisplayManager.unregisterDisplayTransactionListener(this);
+ mDisplayManagerInternal.unregisterDisplayTransactionListener(this);
}
@Override
@@ -708,7 +710,8 @@
return;
}
- DisplayInfo displayInfo = mDisplayManager.getDisplayInfo(Display.DEFAULT_DISPLAY);
+ DisplayInfo displayInfo =
+ mDisplayManagerInternal.getDisplayInfo(Display.DEFAULT_DISPLAY);
switch (displayInfo.rotation) {
case Surface.ROTATION_0:
mSurfaceControl.setPosition(0, 0);
diff --git a/services/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
similarity index 100%
rename from services/java/com/android/server/power/Notifier.java
rename to services/core/java/com/android/server/power/Notifier.java
diff --git a/services/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
similarity index 83%
rename from services/java/com/android/server/power/PowerManagerService.java
rename to services/core/java/com/android/server/power/PowerManagerService.java
index da9548f..94876bb 100644
--- a/services/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -20,11 +20,11 @@
import com.android.internal.app.IBatteryStats;
import com.android.server.BatteryService;
import com.android.server.EventLogTags;
-import com.android.server.LightsService;
-import com.android.server.TwilightService;
+import com.android.server.ServiceThread;
+import com.android.server.lights.Light;
+import com.android.server.lights.LightsManager;
+import com.android.server.twilight.TwilightManager;
import com.android.server.Watchdog;
-import com.android.server.am.ActivityManagerService;
-import com.android.server.display.DisplayManagerService;
import com.android.server.dreams.DreamManagerService;
import android.Manifest;
@@ -38,16 +38,17 @@
import android.database.ContentObserver;
import android.hardware.SensorManager;
import android.hardware.SystemSensorManager;
+import android.hardware.display.DisplayManagerInternal;
import android.net.Uri;
import android.os.BatteryManager;
import android.os.Binder;
import android.os.Handler;
-import android.os.HandlerThread;
import android.os.IBinder;
import android.os.IPowerManager;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
+import android.os.PowerManagerInternal;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -72,7 +73,7 @@
* The power manager service is responsible for coordinating power management
* functions on the device.
*/
-public final class PowerManagerService extends IPowerManager.Stub
+public final class PowerManagerService extends com.android.server.SystemService
implements Watchdog.Monitor {
private static final String TAG = "PowerManagerService";
@@ -168,12 +169,12 @@
private static final int DREAM_BATTERY_LEVEL_DRAIN_CUTOFF = 5;
private Context mContext;
- private LightsService mLightsService;
+ private LightsManager mLightsManager;
private BatteryService mBatteryService;
- private DisplayManagerService mDisplayManagerService;
+ private DisplayManagerInternal mDisplayManagerInternal;
private IBatteryStats mBatteryStats;
private IAppOpsService mAppOps;
- private HandlerThread mHandlerThread;
+ private ServiceThread mHandlerThread;
private PowerManagerHandler mHandler;
private WindowManagerPolicy mPolicy;
private Notifier mNotifier;
@@ -181,7 +182,7 @@
private WirelessChargerDetector mWirelessChargerDetector;
private SettingsObserver mSettingsObserver;
private DreamManagerService mDreamManager;
- private LightsService.Light mAttentionLight;
+ private Light mAttentionLight;
private final Object mLock = new Object();
@@ -231,9 +232,6 @@
// requested because it is updated asynchronously by the display power controller.
private final DisplayPowerRequest mDisplayPowerRequest = new DisplayPowerRequest();
- // The time the screen was last turned off, in elapsedRealtime() timebase.
- private long mLastScreenOffEventElapsedRealTime;
-
// True if the display power state has been fully applied, which means the display
// is actually on or actually off or whatever was requested.
private boolean mDisplayReady;
@@ -392,25 +390,36 @@
nativeSetPowerState(true, true);
}
+ @Override
+ public void onCreate(Context context) {
+ mContext = context;
+ }
+
+ @Override
+ public void onStart() {
+ publishBinderService(Context.POWER_SERVICE, new BinderService());
+ publishLocalService(PowerManagerInternal.class, new LocalService());
+ }
+
/**
* Initialize the power manager.
* Must be called before any other functions within the power manager are called.
*/
- public void init(Context context, LightsService ls,
- ActivityManagerService am, BatteryService bs, IBatteryStats bss,
- IAppOpsService appOps, DisplayManagerService dm) {
- mContext = context;
- mLightsService = ls;
+ public void init(LightsManager ls,
+ BatteryService bs, IBatteryStats bss,
+ IAppOpsService appOps) {
+ mLightsManager = ls;
mBatteryService = bs;
mBatteryStats = bss;
mAppOps = appOps;
- mDisplayManagerService = dm;
- mHandlerThread = new HandlerThread(TAG);
+ mDisplayManagerInternal = getLocalService(DisplayManagerInternal.class);
+ mHandlerThread = new ServiceThread(TAG,
+ Process.THREAD_PRIORITY_DISPLAY, false /*allowIo*/);
mHandlerThread.start();
mHandler = new PowerManagerHandler(mHandlerThread.getLooper());
Watchdog.getInstance().addMonitor(this);
- Watchdog.getInstance().addThread(mHandler, mHandlerThread.getName());
+ Watchdog.getInstance().addThread(mHandler);
// Forcibly turn the screen on at boot so that it is in a known power state.
// We do this in init() rather than in the constructor because setting the
@@ -421,18 +430,18 @@
mDisplayBlanker.unblankAllDisplays();
}
- public void setPolicy(WindowManagerPolicy policy) {
+ void setPolicy(WindowManagerPolicy policy) {
synchronized (mLock) {
mPolicy = policy;
}
}
- public void systemReady(TwilightService twilight, DreamManagerService dreamManager) {
+ public void systemReady(TwilightManager twilight, DreamManagerService dreamManager) {
synchronized (mLock) {
mSystemReady = true;
mDreamManager = dreamManager;
- PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
+ PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mScreenBrightnessSettingMinimum = pm.getMinimumScreenBrightnessSetting();
mScreenBrightnessSettingMaximum = pm.getMaximumScreenBrightnessSetting();
mScreenBrightnessSettingDefault = pm.getDefaultScreenBrightnessSetting();
@@ -448,15 +457,15 @@
// The display power controller runs on the power manager service's
// own handler thread to ensure timely operation.
mDisplayPowerController = new DisplayPowerController(mHandler.getLooper(),
- mContext, mNotifier, mLightsService, twilight, sensorManager,
- mDisplayManagerService, mDisplaySuspendBlocker, mDisplayBlanker,
+ mContext, mNotifier, mLightsManager, twilight, sensorManager,
+ mDisplaySuspendBlocker, mDisplayBlanker,
mDisplayPowerControllerCallbacks, mHandler);
mWirelessChargerDetector = new WirelessChargerDetector(sensorManager,
createSuspendBlockerLocked("PowerManagerService.WirelessChargerDetector"),
mHandler);
mSettingsObserver = new SettingsObserver(mHandler);
- mAttentionLight = mLightsService.getLight(LightsService.LIGHT_ID_ATTENTION);
+ mAttentionLight = mLightsManager.getLight(LightsManager.LIGHT_ID_ATTENTION);
// Register for broadcasts from other components of the system.
IntentFilter filter = new IntentFilter();
@@ -579,41 +588,6 @@
updatePowerStateLocked();
}
- @Override // Binder call
- public void acquireWakeLockWithUid(IBinder lock, int flags, String tag, String packageName,
- int uid) {
- acquireWakeLock(lock, flags, tag, packageName, new WorkSource(uid));
- }
-
- @Override // Binder call
- public void acquireWakeLock(IBinder lock, int flags, String tag, String packageName,
- WorkSource ws) {
- if (lock == null) {
- throw new IllegalArgumentException("lock must not be null");
- }
- if (packageName == null) {
- throw new IllegalArgumentException("packageName must not be null");
- }
- PowerManager.validateWakeLockParameters(flags, tag);
-
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
- if (ws != null && ws.size() != 0) {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.UPDATE_DEVICE_STATS, null);
- } else {
- ws = null;
- }
-
- final int uid = Binder.getCallingUid();
- final int pid = Binder.getCallingPid();
- final long ident = Binder.clearCallingIdentity();
- try {
- acquireWakeLockInternal(lock, flags, tag, packageName, ws, uid, pid);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
private void acquireWakeLockInternal(IBinder lock, int flags, String tag, String packageName,
WorkSource ws, int uid, int pid) {
synchronized (mLock) {
@@ -668,22 +642,6 @@
}
}
- @Override // Binder call
- public void releaseWakeLock(IBinder lock, int flags) {
- if (lock == null) {
- throw new IllegalArgumentException("lock must not be null");
- }
-
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
-
- final long ident = Binder.clearCallingIdentity();
- try {
- releaseWakeLockInternal(lock, flags);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
private void releaseWakeLockInternal(IBinder lock, int flags) {
synchronized (mLock) {
int index = findWakeLockIndexLocked(lock);
@@ -746,43 +704,6 @@
}
}
- @Override // Binder call
- public void updateWakeLockUids(IBinder lock, int[] uids) {
- WorkSource ws = null;
-
- if (uids != null) {
- ws = new WorkSource();
- // XXX should WorkSource have a way to set uids as an int[] instead of adding them
- // one at a time?
- for (int i = 0; i < uids.length; i++) {
- ws.add(uids[i]);
- }
- }
- updateWakeLockWorkSource(lock, ws);
- }
-
- @Override // Binder call
- public void updateWakeLockWorkSource(IBinder lock, WorkSource ws) {
- if (lock == null) {
- throw new IllegalArgumentException("lock must not be null");
- }
-
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
- if (ws != null && ws.size() != 0) {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.UPDATE_DEVICE_STATS, null);
- } else {
- ws = null;
- }
-
- final long ident = Binder.clearCallingIdentity();
- try {
- updateWakeLockWorkSourceInternal(lock, ws);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
private void updateWakeLockWorkSourceInternal(IBinder lock, WorkSource ws) {
synchronized (mLock) {
int index = findWakeLockIndexLocked(lock);
@@ -834,16 +755,6 @@
}
}
- @Override // Binder call
- public boolean isWakeLockLevelSupported(int level) {
- final long ident = Binder.clearCallingIdentity();
- try {
- return isWakeLockLevelSupportedInternal(level);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
@SuppressWarnings("deprecation")
private boolean isWakeLockLevelSupportedInternal(int level) {
synchronized (mLock) {
@@ -863,40 +774,6 @@
}
}
- @Override // Binder call
- public void userActivity(long eventTime, int event, int flags) {
- final long now = SystemClock.uptimeMillis();
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER)
- != PackageManager.PERMISSION_GRANTED) {
- // Once upon a time applications could call userActivity().
- // Now we require the DEVICE_POWER permission. Log a warning and ignore the
- // request instead of throwing a SecurityException so we don't break old apps.
- synchronized (mLock) {
- if (now >= mLastWarningAboutUserActivityPermission + (5 * 60 * 1000)) {
- mLastWarningAboutUserActivityPermission = now;
- Slog.w(TAG, "Ignoring call to PowerManager.userActivity() because the "
- + "caller does not have DEVICE_POWER permission. "
- + "Please fix your app! "
- + " pid=" + Binder.getCallingPid()
- + " uid=" + Binder.getCallingUid());
- }
- }
- return;
- }
-
- if (eventTime > SystemClock.uptimeMillis()) {
- throw new IllegalArgumentException("event time must not be in the future");
- }
-
- final int uid = Binder.getCallingUid();
- final long ident = Binder.clearCallingIdentity();
- try {
- userActivityInternal(eventTime, event, flags, uid);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
// Called from native code.
private void userActivityFromNative(long eventTime, int event, int flags) {
userActivityInternal(eventTime, event, flags, Process.SYSTEM_UID);
@@ -941,22 +818,6 @@
return false;
}
- @Override // Binder call
- public void wakeUp(long eventTime) {
- if (eventTime > SystemClock.uptimeMillis()) {
- throw new IllegalArgumentException("event time must not be in the future");
- }
-
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
-
- final long ident = Binder.clearCallingIdentity();
- try {
- wakeUpInternal(eventTime);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
// Called from native code.
private void wakeUpFromNative(long eventTime) {
wakeUpInternal(eventTime);
@@ -1004,22 +865,6 @@
return true;
}
- @Override // Binder call
- public void goToSleep(long eventTime, int reason) {
- if (eventTime > SystemClock.uptimeMillis()) {
- throw new IllegalArgumentException("event time must not be in the future");
- }
-
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
-
- final long ident = Binder.clearCallingIdentity();
- try {
- goToSleepInternal(eventTime, reason);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
// Called from native code.
private void goToSleepFromNative(long eventTime, int reason) {
goToSleepInternal(eventTime, reason);
@@ -1082,22 +927,6 @@
return true;
}
- @Override // Binder call
- public void nap(long eventTime) {
- if (eventTime > SystemClock.uptimeMillis()) {
- throw new IllegalArgumentException("event time must not be in the future");
- }
-
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
-
- final long ident = Binder.clearCallingIdentity();
- try {
- napInternal(eventTime);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
private void napInternal(long eventTime) {
synchronized (mLock) {
if (napNoUpdateLocked(eventTime)) {
@@ -1656,12 +1485,6 @@
| DIRTY_SETTINGS | DIRTY_SCREEN_ON_BLOCKER_RELEASED)) != 0) {
int newScreenState = getDesiredScreenPowerStateLocked();
if (newScreenState != mDisplayPowerRequest.screenState) {
- if (newScreenState == DisplayPowerRequest.SCREEN_STATE_OFF
- && mDisplayPowerRequest.screenState
- != DisplayPowerRequest.SCREEN_STATE_OFF) {
- mLastScreenOffEventElapsedRealTime = SystemClock.elapsedRealtime();
- }
-
mDisplayPowerRequest.screenState = newScreenState;
nativeSetPowerState(
newScreenState != DisplayPowerRequest.SCREEN_STATE_OFF,
@@ -1828,16 +1651,6 @@
return false;
}
- @Override // Binder call
- public boolean isScreenOn() {
- final long ident = Binder.clearCallingIdentity();
- try {
- return isScreenOnInternal();
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
private boolean isScreenOnInternal() {
synchronized (mLock) {
return !mSystemReady
@@ -1882,43 +1695,6 @@
updatePowerStateLocked();
}
- /**
- * Reboots the device.
- *
- * @param confirm If true, shows a reboot confirmation dialog.
- * @param reason The reason for the reboot, or null if none.
- * @param wait If true, this call waits for the reboot to complete and does not return.
- */
- @Override // Binder call
- public void reboot(boolean confirm, String reason, boolean wait) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
-
- final long ident = Binder.clearCallingIdentity();
- try {
- shutdownOrRebootInternal(false, confirm, reason, wait);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
- /**
- * Shuts down the device.
- *
- * @param confirm If true, shows a shutdown confirmation dialog.
- * @param wait If true, this call waits for the shutdown to complete and does not return.
- */
- @Override // Binder call
- public void shutdown(boolean confirm, boolean wait) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
-
- final long ident = Binder.clearCallingIdentity();
- try {
- shutdownOrRebootInternal(true, confirm, null, wait);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
private void shutdownOrRebootInternal(final boolean shutdown, final boolean confirm,
final String reason, boolean wait) {
if (mHandler == null || !mSystemReady) {
@@ -1956,22 +1732,6 @@
}
}
- /**
- * Crash the runtime (causing a complete restart of the Android framework).
- * Requires REBOOT permission. Mostly for testing. Should not return.
- */
- @Override // Binder call
- public void crash(String message) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
-
- final long ident = Binder.clearCallingIdentity();
- try {
- crashInternal(message);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
private void crashInternal(final String message) {
Thread t = new Thread("PowerManagerService.crash()") {
@Override
@@ -1987,51 +1747,11 @@
}
}
- /**
- * Set the setting that determines whether the device stays on when plugged in.
- * The argument is a bit string, with each bit specifying a power source that,
- * when the device is connected to that source, causes the device to stay on.
- * See {@link android.os.BatteryManager} for the list of power sources that
- * can be specified. Current values include {@link android.os.BatteryManager#BATTERY_PLUGGED_AC}
- * and {@link android.os.BatteryManager#BATTERY_PLUGGED_USB}
- *
- * Used by "adb shell svc power stayon ..."
- *
- * @param val an {@code int} containing the bits that specify which power sources
- * should cause the device to stay on.
- */
- @Override // Binder call
- public void setStayOnSetting(int val) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SETTINGS, null);
-
- final long ident = Binder.clearCallingIdentity();
- try {
- setStayOnSettingInternal(val);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
private void setStayOnSettingInternal(int val) {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.STAY_ON_WHILE_PLUGGED_IN, val);
}
- /**
- * Used by device administration to set the maximum screen off timeout.
- *
- * This method must only be called by the device administration policy manager.
- */
- @Override // Binder call
- public void setMaximumScreenOffTimeoutFromDeviceAdmin(int timeMs) {
- final long ident = Binder.clearCallingIdentity();
- try {
- setMaximumScreenOffTimeoutFromDeviceAdminInternal(timeMs);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
private void setMaximumScreenOffTimeoutFromDeviceAdminInternal(int timeMs) {
synchronized (mLock) {
mMaximumScreenOffTimeoutFromDeviceAdmin = timeMs;
@@ -2045,23 +1765,8 @@
&& mMaximumScreenOffTimeoutFromDeviceAdmin < Integer.MAX_VALUE;
}
- /**
- * Used by the phone application to make the attention LED flash when ringing.
- */
- @Override // Binder call
- public void setAttentionLight(boolean on, int color) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
-
- final long ident = Binder.clearCallingIdentity();
- try {
- setAttentionLightInternal(on, color);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
private void setAttentionLightInternal(boolean on, int color) {
- LightsService.Light light;
+ Light light;
synchronized (mLock) {
if (!mSystemReady) {
return;
@@ -2070,38 +1775,7 @@
}
// Control light outside of lock.
- light.setFlashing(color, LightsService.LIGHT_FLASH_HARDWARE, (on ? 3 : 0), 0);
- }
-
- /**
- * Used by the Watchdog.
- */
- public long timeSinceScreenWasLastOn() {
- synchronized (mLock) {
- if (mDisplayPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) {
- return 0;
- }
- return SystemClock.elapsedRealtime() - mLastScreenOffEventElapsedRealTime;
- }
- }
-
- /**
- * Used by the window manager to override the screen brightness based on the
- * current foreground activity.
- *
- * This method must only be called by the window manager.
- *
- * @param brightness The overridden brightness, or -1 to disable the override.
- */
- public void setScreenBrightnessOverrideFromWindowManager(int brightness) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
-
- final long ident = Binder.clearCallingIdentity();
- try {
- setScreenBrightnessOverrideFromWindowManagerInternal(brightness);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
+ light.setFlashing(color, Light.LIGHT_FLASH_HARDWARE, (on ? 3 : 0), 0);
}
private void setScreenBrightnessOverrideFromWindowManagerInternal(int brightness) {
@@ -2114,40 +1788,6 @@
}
}
- /**
- * Used by the window manager to override the button brightness based on the
- * current foreground activity.
- *
- * This method must only be called by the window manager.
- *
- * @param brightness The overridden brightness, or -1 to disable the override.
- */
- public void setButtonBrightnessOverrideFromWindowManager(int brightness) {
- // Do nothing.
- // Button lights are not currently supported in the new implementation.
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
- }
-
- /**
- * Used by the window manager to override the user activity timeout based on the
- * current foreground activity. It can only be used to make the timeout shorter
- * than usual, not longer.
- *
- * This method must only be called by the window manager.
- *
- * @param timeoutMillis The overridden timeout, or -1 to disable the override.
- */
- public void setUserActivityTimeoutOverrideFromWindowManager(long timeoutMillis) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
-
- final long ident = Binder.clearCallingIdentity();
- try {
- setUserActivityTimeoutOverrideFromWindowManagerInternal(timeoutMillis);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
private void setUserActivityTimeoutOverrideFromWindowManagerInternal(long timeoutMillis) {
synchronized (mLock) {
if (mUserActivityTimeoutOverrideFromWindowManager != timeoutMillis) {
@@ -2158,30 +1798,6 @@
}
}
- /**
- * Used by the settings application and brightness control widgets to
- * temporarily override the current screen brightness setting so that the
- * user can observe the effect of an intended settings change without applying
- * it immediately.
- *
- * The override will be canceled when the setting value is next updated.
- *
- * @param brightness The overridden brightness.
- *
- * @see android.provider.Settings.System#SCREEN_BRIGHTNESS
- */
- @Override // Binder call
- public void setTemporaryScreenBrightnessSettingOverride(int brightness) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
-
- final long ident = Binder.clearCallingIdentity();
- try {
- setTemporaryScreenBrightnessSettingOverrideInternal(brightness);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
private void setTemporaryScreenBrightnessSettingOverrideInternal(int brightness) {
synchronized (mLock) {
if (mTemporaryScreenBrightnessSettingOverride != brightness) {
@@ -2192,30 +1808,6 @@
}
}
- /**
- * Used by the settings application and brightness control widgets to
- * temporarily override the current screen auto-brightness adjustment setting so that the
- * user can observe the effect of an intended settings change without applying
- * it immediately.
- *
- * The override will be canceled when the setting value is next updated.
- *
- * @param adj The overridden brightness, or Float.NaN to disable the override.
- *
- * @see Settings.System#SCREEN_AUTO_BRIGHTNESS_ADJ
- */
- @Override // Binder call
- public void setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(float adj) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
-
- final long ident = Binder.clearCallingIdentity();
- try {
- setTemporaryScreenAutoBrightnessAdjustmentSettingOverrideInternal(adj);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
private void setTemporaryScreenAutoBrightnessAdjustmentSettingOverrideInternal(float adj) {
synchronized (mLock) {
// Note: This condition handles NaN because NaN is not equal to any other
@@ -2262,16 +1854,7 @@
}
}
- @Override // Binder call
- protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump PowerManager from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
-
+ private void dumpInternal(PrintWriter pw) {
pw.println("POWER MANAGER (dumpsys power)\n");
final DisplayPowerController dpc;
@@ -2712,7 +2295,7 @@
public void blankAllDisplays() {
synchronized (this) {
mBlanked = true;
- mDisplayManagerService.blankAllDisplaysFromPowerManager();
+ mDisplayManagerInternal.blankAllDisplaysFromPowerManager();
nativeSetInteractive(false);
nativeSetAutoSuspend(true);
}
@@ -2723,7 +2306,7 @@
synchronized (this) {
nativeSetAutoSuspend(false);
nativeSetInteractive(true);
- mDisplayManagerService.unblankAllDisplaysFromPowerManager();
+ mDisplayManagerInternal.unblankAllDisplaysFromPowerManager();
mBlanked = false;
}
}
@@ -2735,4 +2318,444 @@
}
}
}
+
+ private final class BinderService extends IPowerManager.Stub {
+ @Override // Binder call
+ public void acquireWakeLockWithUid(IBinder lock, int flags, String tag,
+ String packageName, int uid) {
+ acquireWakeLock(lock, flags, tag, packageName, new WorkSource(uid));
+ }
+
+ @Override // Binder call
+ public void acquireWakeLock(IBinder lock, int flags, String tag, String packageName,
+ WorkSource ws) {
+ if (lock == null) {
+ throw new IllegalArgumentException("lock must not be null");
+ }
+ if (packageName == null) {
+ throw new IllegalArgumentException("packageName must not be null");
+ }
+ PowerManager.validateWakeLockParameters(flags, tag);
+
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
+ if (ws != null && ws.size() != 0) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.UPDATE_DEVICE_STATS, null);
+ } else {
+ ws = null;
+ }
+
+ final int uid = Binder.getCallingUid();
+ final int pid = Binder.getCallingPid();
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ acquireWakeLockInternal(lock, flags, tag, packageName, ws, uid, pid);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override // Binder call
+ public void releaseWakeLock(IBinder lock, int flags) {
+ if (lock == null) {
+ throw new IllegalArgumentException("lock must not be null");
+ }
+
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ releaseWakeLockInternal(lock, flags);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override // Binder call
+ public void updateWakeLockUids(IBinder lock, int[] uids) {
+ WorkSource ws = null;
+
+ if (uids != null) {
+ ws = new WorkSource();
+ // XXX should WorkSource have a way to set uids as an int[] instead of adding them
+ // one at a time?
+ for (int i = 0; i < uids.length; i++) {
+ ws.add(uids[i]);
+ }
+ }
+ updateWakeLockWorkSource(lock, ws);
+ }
+
+ @Override // Binder call
+ public void updateWakeLockWorkSource(IBinder lock, WorkSource ws) {
+ if (lock == null) {
+ throw new IllegalArgumentException("lock must not be null");
+ }
+
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
+ if (ws != null && ws.size() != 0) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.UPDATE_DEVICE_STATS, null);
+ } else {
+ ws = null;
+ }
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ updateWakeLockWorkSourceInternal(lock, ws);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override // Binder call
+ public boolean isWakeLockLevelSupported(int level) {
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ return isWakeLockLevelSupportedInternal(level);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override // Binder call
+ public void userActivity(long eventTime, int event, int flags) {
+ final long now = SystemClock.uptimeMillis();
+ if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER)
+ != PackageManager.PERMISSION_GRANTED) {
+ // Once upon a time applications could call userActivity().
+ // Now we require the DEVICE_POWER permission. Log a warning and ignore the
+ // request instead of throwing a SecurityException so we don't break old apps.
+ synchronized (mLock) {
+ if (now >= mLastWarningAboutUserActivityPermission + (5 * 60 * 1000)) {
+ mLastWarningAboutUserActivityPermission = now;
+ Slog.w(TAG, "Ignoring call to PowerManager.userActivity() because the "
+ + "caller does not have DEVICE_POWER permission. "
+ + "Please fix your app! "
+ + " pid=" + Binder.getCallingPid()
+ + " uid=" + Binder.getCallingUid());
+ }
+ }
+ return;
+ }
+
+ if (eventTime > SystemClock.uptimeMillis()) {
+ throw new IllegalArgumentException("event time must not be in the future");
+ }
+
+ final int uid = Binder.getCallingUid();
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ userActivityInternal(eventTime, event, flags, uid);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override // Binder call
+ public void wakeUp(long eventTime) {
+ if (eventTime > SystemClock.uptimeMillis()) {
+ throw new IllegalArgumentException("event time must not be in the future");
+ }
+
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.DEVICE_POWER, null);
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ wakeUpInternal(eventTime);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override // Binder call
+ public void goToSleep(long eventTime, int reason) {
+ if (eventTime > SystemClock.uptimeMillis()) {
+ throw new IllegalArgumentException("event time must not be in the future");
+ }
+
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.DEVICE_POWER, null);
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ goToSleepInternal(eventTime, reason);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override // Binder call
+ public void nap(long eventTime) {
+ if (eventTime > SystemClock.uptimeMillis()) {
+ throw new IllegalArgumentException("event time must not be in the future");
+ }
+
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.DEVICE_POWER, null);
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ napInternal(eventTime);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override // Binder call
+ public boolean isScreenOn() {
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ return isScreenOnInternal();
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ /**
+ * Reboots the device.
+ *
+ * @param confirm If true, shows a reboot confirmation dialog.
+ * @param reason The reason for the reboot, or null if none.
+ * @param wait If true, this call waits for the reboot to complete and does not return.
+ */
+ @Override // Binder call
+ public void reboot(boolean confirm, String reason, boolean wait) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ shutdownOrRebootInternal(false, confirm, reason, wait);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ /**
+ * Shuts down the device.
+ *
+ * @param confirm If true, shows a shutdown confirmation dialog.
+ * @param wait If true, this call waits for the shutdown to complete and does not return.
+ */
+ @Override // Binder call
+ public void shutdown(boolean confirm, boolean wait) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ shutdownOrRebootInternal(true, confirm, null, wait);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ /**
+ * Crash the runtime (causing a complete restart of the Android framework).
+ * Requires REBOOT permission. Mostly for testing. Should not return.
+ */
+ @Override // Binder call
+ public void crash(String message) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ crashInternal(message);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ /**
+ * Set the setting that determines whether the device stays on when plugged in.
+ * The argument is a bit string, with each bit specifying a power source that,
+ * when the device is connected to that source, causes the device to stay on.
+ * See {@link android.os.BatteryManager} for the list of power sources that
+ * can be specified. Current values include
+ * {@link android.os.BatteryManager#BATTERY_PLUGGED_AC}
+ * and {@link android.os.BatteryManager#BATTERY_PLUGGED_USB}
+ *
+ * Used by "adb shell svc power stayon ..."
+ *
+ * @param val an {@code int} containing the bits that specify which power sources
+ * should cause the device to stay on.
+ */
+ @Override // Binder call
+ public void setStayOnSetting(int val) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.WRITE_SETTINGS, null);
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ setStayOnSettingInternal(val);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ /**
+ * Used by device administration to set the maximum screen off timeout.
+ *
+ * This method must only be called by the device administration policy manager.
+ */
+ @Override // Binder call
+ public void setMaximumScreenOffTimeoutFromDeviceAdmin(int timeMs) {
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ setMaximumScreenOffTimeoutFromDeviceAdminInternal(timeMs);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ /**
+ * Used by the settings application and brightness control widgets to
+ * temporarily override the current screen brightness setting so that the
+ * user can observe the effect of an intended settings change without applying
+ * it immediately.
+ *
+ * The override will be canceled when the setting value is next updated.
+ *
+ * @param brightness The overridden brightness.
+ *
+ * @see android.provider.Settings.System#SCREEN_BRIGHTNESS
+ */
+ @Override // Binder call
+ public void setTemporaryScreenBrightnessSettingOverride(int brightness) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.DEVICE_POWER, null);
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ setTemporaryScreenBrightnessSettingOverrideInternal(brightness);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ /**
+ * Used by the settings application and brightness control widgets to
+ * temporarily override the current screen auto-brightness adjustment setting so that the
+ * user can observe the effect of an intended settings change without applying
+ * it immediately.
+ *
+ * The override will be canceled when the setting value is next updated.
+ *
+ * @param adj The overridden brightness, or Float.NaN to disable the override.
+ *
+ * @see Settings.System#SCREEN_AUTO_BRIGHTNESS_ADJ
+ */
+ @Override // Binder call
+ public void setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(float adj) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.DEVICE_POWER, null);
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ setTemporaryScreenAutoBrightnessAdjustmentSettingOverrideInternal(adj);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ /**
+ * Used by the phone application to make the attention LED flash when ringing.
+ */
+ @Override // Binder call
+ public void setAttentionLight(boolean on, int color) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.DEVICE_POWER, null);
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ setAttentionLightInternal(on, color);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override // Binder call
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
+ != PackageManager.PERMISSION_GRANTED) {
+ pw.println("Permission Denial: can't dump PowerManager from from pid="
+ + Binder.getCallingPid()
+ + ", uid=" + Binder.getCallingUid());
+ return;
+ }
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ dumpInternal(pw);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+ }
+
+ private final class LocalService extends PowerManagerInternal {
+ /**
+ * Used by the window manager to override the screen brightness based on the
+ * current foreground activity.
+ *
+ * This method must only be called by the window manager.
+ *
+ * @param brightness The overridden brightness, or -1 to disable the override.
+ */
+ @Override
+ public void setScreenBrightnessOverrideFromWindowManager(int brightness) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.DEVICE_POWER, null);
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ setScreenBrightnessOverrideFromWindowManagerInternal(brightness);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ /**
+ * Used by the window manager to override the button brightness based on the
+ * current foreground activity.
+ *
+ * This method must only be called by the window manager.
+ *
+ * @param brightness The overridden brightness, or -1 to disable the override.
+ */
+ @Override
+ public void setButtonBrightnessOverrideFromWindowManager(int brightness) {
+ // Do nothing.
+ // Button lights are not currently supported in the new implementation.
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.DEVICE_POWER, null);
+ }
+
+ /**
+ * Used by the window manager to override the user activity timeout based on the
+ * current foreground activity. It can only be used to make the timeout shorter
+ * than usual, not longer.
+ *
+ * This method must only be called by the window manager.
+ *
+ * @param timeoutMillis The overridden timeout, or -1 to disable the override.
+ */
+ @Override
+ public void setUserActivityTimeoutOverrideFromWindowManager(long timeoutMillis) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.DEVICE_POWER, null);
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ setUserActivityTimeoutOverrideFromWindowManagerInternal(timeoutMillis);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override
+ public void setPolicy(WindowManagerPolicy policy) {
+ PowerManagerService.this.setPolicy(policy);
+ }
+ }
}
diff --git a/services/java/com/android/server/power/RampAnimator.java b/services/core/java/com/android/server/power/RampAnimator.java
similarity index 100%
rename from services/java/com/android/server/power/RampAnimator.java
rename to services/core/java/com/android/server/power/RampAnimator.java
diff --git a/services/java/com/android/server/power/ScreenOnBlocker.java b/services/core/java/com/android/server/power/ScreenOnBlocker.java
similarity index 100%
rename from services/java/com/android/server/power/ScreenOnBlocker.java
rename to services/core/java/com/android/server/power/ScreenOnBlocker.java
diff --git a/services/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java
similarity index 100%
rename from services/java/com/android/server/power/ShutdownThread.java
rename to services/core/java/com/android/server/power/ShutdownThread.java
diff --git a/services/java/com/android/server/power/SuspendBlocker.java b/services/core/java/com/android/server/power/SuspendBlocker.java
similarity index 100%
rename from services/java/com/android/server/power/SuspendBlocker.java
rename to services/core/java/com/android/server/power/SuspendBlocker.java
diff --git a/services/java/com/android/server/power/WirelessChargerDetector.java b/services/core/java/com/android/server/power/WirelessChargerDetector.java
similarity index 100%
rename from services/java/com/android/server/power/WirelessChargerDetector.java
rename to services/core/java/com/android/server/power/WirelessChargerDetector.java
diff --git a/services/java/com/android/server/search/SearchManagerService.java b/services/core/java/com/android/server/search/SearchManagerService.java
similarity index 100%
rename from services/java/com/android/server/search/SearchManagerService.java
rename to services/core/java/com/android/server/search/SearchManagerService.java
diff --git a/services/java/com/android/server/search/Searchables.java b/services/core/java/com/android/server/search/Searchables.java
similarity index 100%
rename from services/java/com/android/server/search/Searchables.java
rename to services/core/java/com/android/server/search/Searchables.java
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
new file mode 100644
index 0000000..4f75189
--- /dev/null
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -0,0 +1,29 @@
+/**
+ * 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.server.statusbar;
+
+import com.android.server.notification.NotificationDelegate;
+
+import android.os.IBinder;
+import android.service.notification.StatusBarNotification;
+
+public interface StatusBarManagerInternal {
+ void setNotificationDelegate(NotificationDelegate delegate);
+ IBinder addNotification(StatusBarNotification notification);
+ void updateNotification(IBinder key, StatusBarNotification notification);
+ void removeNotification(IBinder key);
+}
diff --git a/services/java/com/android/server/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
similarity index 80%
rename from services/java/com/android/server/StatusBarManagerService.java
rename to services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index f207c08..2ae467e 100644
--- a/services/java/com/android/server/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -14,26 +14,28 @@
* limitations under the License.
*/
-package com.android.server;
+package com.android.server.statusbar;
import android.app.StatusBarManager;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Resources;
-import android.os.Binder;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.UserHandle;
import android.util.Slog;
import com.android.internal.statusbar.IStatusBar;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.statusbar.StatusBarIconList;
+import com.android.server.LocalServices;
+import com.android.server.notification.NotificationDelegate;
import com.android.server.wm.WindowManagerService;
import java.io.FileDescriptor;
@@ -51,31 +53,31 @@
public class StatusBarManagerService extends IStatusBarService.Stub
implements WindowManagerService.OnHardKeyboardStatusChangeListener
{
- static final String TAG = "StatusBarManagerService";
- static final boolean SPEW = false;
+ private static final String TAG = "StatusBarManagerService";
+ private static final boolean SPEW = false;
- final Context mContext;
- final WindowManagerService mWindowManager;
- Handler mHandler = new Handler();
- NotificationCallbacks mNotificationCallbacks;
- volatile IStatusBar mBar;
- StatusBarIconList mIcons = new StatusBarIconList();
- HashMap<IBinder,StatusBarNotification> mNotifications
+ private final Context mContext;
+ private final WindowManagerService mWindowManager;
+ private Handler mHandler = new Handler();
+ private NotificationDelegate mNotificationDelegate;
+ private volatile IStatusBar mBar;
+ private StatusBarIconList mIcons = new StatusBarIconList();
+ private HashMap<IBinder,StatusBarNotification> mNotifications
= new HashMap<IBinder,StatusBarNotification>();
// for disabling the status bar
- final ArrayList<DisableRecord> mDisableRecords = new ArrayList<DisableRecord>();
- IBinder mSysUiVisToken = new Binder();
- int mDisabled = 0;
+ private final ArrayList<DisableRecord> mDisableRecords = new ArrayList<DisableRecord>();
+ private IBinder mSysUiVisToken = new Binder();
+ private int mDisabled = 0;
- Object mLock = new Object();
+ private Object mLock = new Object();
// encompasses lights-out mode and other flags defined on View
- int mSystemUiVisibility = 0;
- boolean mMenuVisible = false;
- int mImeWindowVis = 0;
- int mImeBackDisposition;
- IBinder mImeToken = null;
- int mCurrentUserId;
+ private int mSystemUiVisibility = 0;
+ private boolean mMenuVisible = false;
+ private int mImeWindowVis = 0;
+ private int mImeBackDisposition;
+ private IBinder mImeToken = null;
+ private int mCurrentUserId;
private class DisableRecord implements IBinder.DeathRecipient {
int userId;
@@ -90,16 +92,6 @@
}
}
- public interface NotificationCallbacks {
- void onSetDisabled(int status);
- void onClearAll();
- void onNotificationClick(String pkg, String tag, int id);
- void onNotificationClear(String pkg, String tag, int id);
- void onPanelRevealed();
- void onNotificationError(String pkg, String tag, int id,
- int uid, int initialPid, String message);
- }
-
/**
* Construct the service, add the status bar view to the window manager
*/
@@ -110,15 +102,74 @@
final Resources res = context.getResources();
mIcons.defineSlots(res.getStringArray(com.android.internal.R.array.config_statusBarIcons));
+
+ LocalServices.addService(StatusBarManagerInternal.class, mInternalService);
}
- public void setNotificationCallbacks(NotificationCallbacks listener) {
- mNotificationCallbacks = listener;
- }
+ /**
+ * Private API used by NotificationManagerService.
+ */
+ private final StatusBarManagerInternal mInternalService = new StatusBarManagerInternal() {
+ @Override
+ public void setNotificationDelegate(NotificationDelegate delegate) {
+ synchronized (mNotifications) {
+ mNotificationDelegate = delegate;
+ }
+ }
+
+ @Override
+ public IBinder addNotification(StatusBarNotification notification) {
+ synchronized (mNotifications) {
+ IBinder key = new Binder();
+ mNotifications.put(key, notification);
+ if (mBar != null) {
+ try {
+ mBar.addNotification(key, notification);
+ } catch (RemoteException ex) {
+ }
+ }
+ return key;
+ }
+ }
+
+ @Override
+ public void updateNotification(IBinder key, StatusBarNotification notification) {
+ synchronized (mNotifications) {
+ if (!mNotifications.containsKey(key)) {
+ throw new IllegalArgumentException("updateNotification key not found: " + key);
+ }
+ mNotifications.put(key, notification);
+ if (mBar != null) {
+ try {
+ mBar.updateNotification(key, notification);
+ } catch (RemoteException ex) {
+ }
+ }
+ }
+ }
+
+ @Override
+ public void removeNotification(IBinder key) {
+ synchronized (mNotifications) {
+ final StatusBarNotification n = mNotifications.remove(key);
+ if (n == null) {
+ Slog.e(TAG, "removeNotification key not found: " + key);
+ return;
+ }
+ if (mBar != null) {
+ try {
+ mBar.removeNotification(key);
+ } catch (RemoteException ex) {
+ }
+ }
+ }
+ }
+ };
// ================================================================================
// From IStatusBarService
// ================================================================================
+ @Override
public void expandNotificationsPanel() {
enforceExpandStatusBar();
@@ -130,6 +181,7 @@
}
}
+ @Override
public void collapsePanels() {
enforceExpandStatusBar();
@@ -141,6 +193,7 @@
}
}
+ @Override
public void expandSettingsPanel() {
enforceExpandStatusBar();
@@ -152,6 +205,7 @@
}
}
+ @Override
public void disable(int what, IBinder token, String pkg) {
disableInternal(mCurrentUserId, what, token, pkg);
}
@@ -177,7 +231,7 @@
mDisabled = net;
mHandler.post(new Runnable() {
public void run() {
- mNotificationCallbacks.onSetDisabled(net);
+ mNotificationDelegate.onSetDisabled(net);
}
});
if (mBar != null) {
@@ -189,6 +243,7 @@
}
}
+ @Override
public void setIcon(String slot, String iconPackage, int iconId, int iconLevel,
String contentDescription) {
enforceStatusBar();
@@ -214,6 +269,7 @@
}
}
+ @Override
public void setIconVisibility(String slot, boolean visible) {
enforceStatusBar();
@@ -241,6 +297,7 @@
}
}
+ @Override
public void removeIcon(String slot) {
enforceStatusBar();
@@ -265,6 +322,7 @@
* Hide or show the on-screen Menu key. Only call this from the window manager, typically in
* response to a window with FLAG_NEEDS_MENU_KEY set.
*/
+ @Override
public void topAppWindowChanged(final boolean menuVisible) {
enforceStatusBar();
@@ -285,6 +343,7 @@
}
}
+ @Override
public void setImeWindowStatus(final IBinder token, final int vis, final int backDisposition) {
enforceStatusBar();
@@ -312,6 +371,7 @@
}
}
+ @Override
public void setSystemUiVisibility(int vis, int mask) {
// also allows calls from window manager which is in this process.
enforceStatusBarService();
@@ -344,6 +404,7 @@
}
}
+ @Override
public void setHardKeyboardEnabled(final boolean enabled) {
mHandler.post(new Runnable() {
public void run() {
@@ -426,6 +487,7 @@
// ================================================================================
// Callbacks from the status bar service.
// ================================================================================
+ @Override
public void registerStatusBar(IStatusBar bar, StatusBarIconList iconList,
List<IBinder> notificationKeys, List<StatusBarNotification> notifications,
int switches[], List<IBinder> binders) {
@@ -458,86 +520,64 @@
* The status bar service should call this each time the user brings the panel from
* invisible to visible in order to clear the notification light.
*/
+ @Override
public void onPanelRevealed() {
enforceStatusBarService();
-
- // tell the notification manager to turn off the lights.
- mNotificationCallbacks.onPanelRevealed();
+ long identity = Binder.clearCallingIdentity();
+ try {
+ // tell the notification manager to turn off the lights.
+ mNotificationDelegate.onPanelRevealed();
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
+ @Override
public void onNotificationClick(String pkg, String tag, int id) {
enforceStatusBarService();
-
- mNotificationCallbacks.onNotificationClick(pkg, tag, id);
+ long identity = Binder.clearCallingIdentity();
+ try {
+ mNotificationDelegate.onNotificationClick(pkg, tag, id);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
+ @Override
public void onNotificationError(String pkg, String tag, int id,
int uid, int initialPid, String message) {
enforceStatusBarService();
-
- // WARNING: this will call back into us to do the remove. Don't hold any locks.
- mNotificationCallbacks.onNotificationError(pkg, tag, id, uid, initialPid, message);
+ long identity = Binder.clearCallingIdentity();
+ try {
+ // WARNING: this will call back into us to do the remove. Don't hold any locks.
+ mNotificationDelegate.onNotificationError(pkg, tag, id, uid, initialPid, message);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
+ @Override
public void onNotificationClear(String pkg, String tag, int id) {
enforceStatusBarService();
-
- mNotificationCallbacks.onNotificationClear(pkg, tag, id);
+ long identity = Binder.clearCallingIdentity();
+ try {
+ mNotificationDelegate.onNotificationClear(pkg, tag, id);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
+ @Override
public void onClearAllNotifications() {
enforceStatusBarService();
-
- mNotificationCallbacks.onClearAll();
- }
-
- // ================================================================================
- // Callbacks for NotificationManagerService.
- // ================================================================================
- public IBinder addNotification(StatusBarNotification notification) {
- synchronized (mNotifications) {
- IBinder key = new Binder();
- mNotifications.put(key, notification);
- if (mBar != null) {
- try {
- mBar.addNotification(key, notification);
- } catch (RemoteException ex) {
- }
- }
- return key;
+ long identity = Binder.clearCallingIdentity();
+ try {
+ mNotificationDelegate.onClearAll();
+ } finally {
+ Binder.restoreCallingIdentity(identity);
}
}
- public void updateNotification(IBinder key, StatusBarNotification notification) {
- synchronized (mNotifications) {
- if (!mNotifications.containsKey(key)) {
- throw new IllegalArgumentException("updateNotification key not found: " + key);
- }
- mNotifications.put(key, notification);
- if (mBar != null) {
- try {
- mBar.updateNotification(key, notification);
- } catch (RemoteException ex) {
- }
- }
- }
- }
-
- public void removeNotification(IBinder key) {
- synchronized (mNotifications) {
- final StatusBarNotification n = mNotifications.remove(key);
- if (n == null) {
- Slog.e(TAG, "removeNotification key not found: " + key);
- return;
- }
- if (mBar != null) {
- try {
- mBar.removeNotification(key);
- } catch (RemoteException ex) {
- }
- }
- }
- }
// ================================================================================
// Can be called from any thread
diff --git a/services/core/java/com/android/server/storage/DeviceStorageMonitorInternal.java b/services/core/java/com/android/server/storage/DeviceStorageMonitorInternal.java
new file mode 100644
index 0000000..a91a81b
--- /dev/null
+++ b/services/core/java/com/android/server/storage/DeviceStorageMonitorInternal.java
@@ -0,0 +1,24 @@
+/**
+ * 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.server.storage;
+
+public interface DeviceStorageMonitorInternal {
+ boolean isMemoryLow();
+ long getMemoryLowThreshold();
+ void checkMemory();
+}
+
diff --git a/services/java/com/android/server/DeviceStorageMonitorService.java b/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
similarity index 79%
rename from services/java/com/android/server/DeviceStorageMonitorService.java
rename to services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
index 016c561..8805084 100644
--- a/services/java/com/android/server/DeviceStorageMonitorService.java
+++ b/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
@@ -14,7 +14,10 @@
* limitations under the License.
*/
-package com.android.server;
+package com.android.server.storage;
+
+import com.android.server.EventLogTags;
+import com.android.server.SystemService;
import android.app.Notification;
import android.app.NotificationManager;
@@ -29,8 +32,8 @@
import android.os.Environment;
import android.os.FileObserver;
import android.os.Handler;
+import android.os.IBinder;
import android.os.Message;
-import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.StatFs;
@@ -66,13 +69,13 @@
* settings parameter with a default value of 2MB), the free memory is
* logged to the event log.
*/
-public class DeviceStorageMonitorService extends Binder {
- private static final String TAG = "DeviceStorageMonitorService";
+public class DeviceStorageMonitorService extends SystemService {
+ static final String TAG = "DeviceStorageMonitorService";
- private static final boolean DEBUG = false;
- private static final boolean localLOGV = false;
+ static final boolean DEBUG = false;
+ static final boolean localLOGV = false;
- private static final int DEVICE_MEMORY_WHAT = 1;
+ static final int DEVICE_MEMORY_WHAT = 1;
private static final int MONITOR_INTERVAL = 1; //in minutes
private static final int LOW_MEMORY_NOTIFICATION_ID = 1;
@@ -84,9 +87,8 @@
private long mFreeMemAfterLastCacheClear; // on /data
private long mLastReportedFreeMem;
private long mLastReportedFreeMemTime;
- private boolean mLowMemFlag=false;
+ boolean mLowMemFlag=false;
private boolean mMemFullFlag=false;
- private Context mContext;
private ContentResolver mResolver;
private long mTotalMemory; // on /data
private StatFs mDataFileStats;
@@ -98,19 +100,19 @@
private static final File CACHE_PATH = Environment.getDownloadCacheDirectory();
private long mThreadStartTime = -1;
- private boolean mClearSucceeded = false;
- private boolean mClearingCache;
+ boolean mClearSucceeded = false;
+ boolean mClearingCache;
private Intent mStorageLowIntent;
private Intent mStorageOkIntent;
private Intent mStorageFullIntent;
private Intent mStorageNotFullIntent;
private CachePackageDataObserver mClearCacheObserver;
- private final CacheFileDeletedObserver mCacheFileDeletedObserver;
+ private CacheFileDeletedObserver mCacheFileDeletedObserver;
private static final int _TRUE = 1;
private static final int _FALSE = 0;
// This is the raw threshold that has been set at which we consider
// storage to be low.
- private long mMemLowThreshold;
+ long mMemLowThreshold;
// This is the threshold at which we start trying to flush caches
// to get below the low threshold limit. It is less than the low
// threshold; we will allow storage to get a bit beyond the limit
@@ -126,13 +128,13 @@
/**
* This string is used for ServiceManager access to this class.
*/
- public static final String SERVICE = "devicestoragemonitor";
+ static final String SERVICE = "devicestoragemonitor";
/**
* Handler that checks the amount of disk space on the device and sends a
* notification if the device runs low on disk space
*/
- Handler mHandler = new Handler() {
+ private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
//don't handle an invalid message
@@ -144,7 +146,7 @@
}
};
- class CachePackageDataObserver extends IPackageDataObserver.Stub {
+ private class CachePackageDataObserver extends IPackageDataObserver.Stub {
public void onRemoveCompleted(String packageName, boolean succeeded) {
mClearSucceeded = succeeded;
mClearingCache = false;
@@ -154,7 +156,7 @@
}
}
- private final void restatDataDir() {
+ private void restatDataDir() {
try {
mDataFileStats.restat(DATA_PATH.getAbsolutePath());
mFreeMem = (long) mDataFileStats.getAvailableBlocks() *
@@ -206,7 +208,7 @@
}
}
- private final void clearCache() {
+ private void clearCache() {
if (mClearCacheObserver == null) {
// Lazy instantiation
mClearCacheObserver = new CachePackageDataObserver();
@@ -223,7 +225,7 @@
}
}
- private final void checkMemory(boolean checkCache) {
+ void checkMemory(boolean checkCache) {
//if the thread that was started to clear cache is still running do nothing till its
//finished clearing cache. Ideally this flag could be modified by clearCache
// and should be accessed via a lock but even if it does this test will fail now and
@@ -300,7 +302,7 @@
postCheckMemoryMsg(true, DEFAULT_CHECK_INTERVAL);
}
- private void postCheckMemoryMsg(boolean clearCache, long delay) {
+ void postCheckMemoryMsg(boolean clearCache, long delay) {
// Remove queued messages
mHandler.removeMessages(DEVICE_MEMORY_WHAT);
mHandler.sendMessageDelayed(mHandler.obtainMessage(DEVICE_MEMORY_WHAT,
@@ -312,10 +314,10 @@
* Constructor to run service. initializes the disk space threshold value
* and posts an empty message to kickstart the process.
*/
- public DeviceStorageMonitorService(Context context) {
+ @Override
+ public void onCreate(Context context) {
mLastReportedFreeMemTime = 0;
- mContext = context;
- mResolver = mContext.getContentResolver();
+ mResolver = context.getContentResolver();
//create StatFs object
mDataFileStats = new StatFs(DATA_PATH.getAbsolutePath());
mSystemFileStats = new StatFs(SYSTEM_PATH.getAbsolutePath());
@@ -331,9 +333,12 @@
mStorageFullIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
mStorageNotFullIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_NOT_FULL);
mStorageNotFullIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ }
+ @Override
+ public void onStart() {
// cache storage thresholds
- final StorageManager sm = StorageManager.from(context);
+ final StorageManager sm = StorageManager.from(getContext());
mMemLowThreshold = sm.getStorageLowBytes(DATA_PATH);
mMemFullThreshold = sm.getStorageFullBytes(DATA_PATH);
@@ -345,6 +350,78 @@
mCacheFileDeletedObserver = new CacheFileDeletedObserver();
mCacheFileDeletedObserver.startWatching();
+
+ publishBinderService(SERVICE, mRemoteService);
+ publishLocalService(DeviceStorageMonitorInternal.class, mLocalService);
+ }
+
+ private final DeviceStorageMonitorInternal mLocalService = new DeviceStorageMonitorInternal() {
+ @Override
+ public void checkMemory() {
+ // force an early check
+ postCheckMemoryMsg(true, 0);
+ }
+
+ @Override
+ public boolean isMemoryLow() {
+ return mLowMemFlag;
+ }
+
+ @Override
+ public long getMemoryLowThreshold() {
+ return mMemLowThreshold;
+ }
+ };
+
+ private final IBinder mRemoteService = new Binder() {
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+ != PackageManager.PERMISSION_GRANTED) {
+
+ pw.println("Permission Denial: can't dump " + SERVICE + " from from pid="
+ + Binder.getCallingPid()
+ + ", uid=" + Binder.getCallingUid());
+ return;
+ }
+
+ dumpImpl(pw);
+ }
+ };
+
+ void dumpImpl(PrintWriter pw) {
+ final Context context = getContext();
+
+ pw.println("Current DeviceStorageMonitor state:");
+
+ pw.print(" mFreeMem="); pw.print(Formatter.formatFileSize(context, mFreeMem));
+ pw.print(" mTotalMemory=");
+ pw.println(Formatter.formatFileSize(context, mTotalMemory));
+
+ pw.print(" mFreeMemAfterLastCacheClear=");
+ pw.println(Formatter.formatFileSize(context, mFreeMemAfterLastCacheClear));
+
+ pw.print(" mLastReportedFreeMem=");
+ pw.print(Formatter.formatFileSize(context, mLastReportedFreeMem));
+ pw.print(" mLastReportedFreeMemTime=");
+ TimeUtils.formatDuration(mLastReportedFreeMemTime, SystemClock.elapsedRealtime(), pw);
+ pw.println();
+
+ pw.print(" mLowMemFlag="); pw.print(mLowMemFlag);
+ pw.print(" mMemFullFlag="); pw.println(mMemFullFlag);
+
+ pw.print(" mClearSucceeded="); pw.print(mClearSucceeded);
+ pw.print(" mClearingCache="); pw.println(mClearingCache);
+
+ pw.print(" mMemLowThreshold=");
+ pw.print(Formatter.formatFileSize(context, mMemLowThreshold));
+ pw.print(" mMemFullThreshold=");
+ pw.println(Formatter.formatFileSize(context, mMemFullThreshold));
+
+ pw.print(" mMemCacheStartTrimThreshold=");
+ pw.print(Formatter.formatFileSize(context, mMemCacheStartTrimThreshold));
+ pw.print(" mMemCacheTrimToThreshold=");
+ pw.println(Formatter.formatFileSize(context, mMemCacheTrimToThreshold));
}
/**
@@ -352,7 +429,8 @@
* an error dialog indicating low disk space and launch the Installer
* application
*/
- private final void sendNotification() {
+ private void sendNotification() {
+ final Context context = getContext();
if(localLOGV) Slog.i(TAG, "Sending low memory notification");
//log the event to event log with the amount of free storage(in bytes) left on the device
EventLog.writeEvent(EventLogTags.LOW_STORAGE, mFreeMem);
@@ -363,86 +441,58 @@
lowMemIntent.putExtra("memory", mFreeMem);
lowMemIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
NotificationManager mNotificationMgr =
- (NotificationManager)mContext.getSystemService(
+ (NotificationManager)context.getSystemService(
Context.NOTIFICATION_SERVICE);
- CharSequence title = mContext.getText(
+ CharSequence title = context.getText(
com.android.internal.R.string.low_internal_storage_view_title);
- CharSequence details = mContext.getText(
+ CharSequence details = context.getText(
com.android.internal.R.string.low_internal_storage_view_text);
- PendingIntent intent = PendingIntent.getActivityAsUser(mContext, 0, lowMemIntent, 0,
+ PendingIntent intent = PendingIntent.getActivityAsUser(context, 0, lowMemIntent, 0,
null, UserHandle.CURRENT);
Notification notification = new Notification();
notification.icon = com.android.internal.R.drawable.stat_notify_disk_full;
notification.tickerText = title;
notification.flags |= Notification.FLAG_NO_CLEAR;
- notification.setLatestEventInfo(mContext, title, details, intent);
+ notification.setLatestEventInfo(context, title, details, intent);
mNotificationMgr.notifyAsUser(null, LOW_MEMORY_NOTIFICATION_ID, notification,
UserHandle.ALL);
- mContext.sendStickyBroadcastAsUser(mStorageLowIntent, UserHandle.ALL);
+ context.sendStickyBroadcastAsUser(mStorageLowIntent, UserHandle.ALL);
}
/**
* Cancels low storage notification and sends OK intent.
*/
- private final void cancelNotification() {
+ private void cancelNotification() {
+ final Context context = getContext();
if(localLOGV) Slog.i(TAG, "Canceling low memory notification");
NotificationManager mNotificationMgr =
- (NotificationManager)mContext.getSystemService(
+ (NotificationManager)context.getSystemService(
Context.NOTIFICATION_SERVICE);
//cancel notification since memory has been freed
mNotificationMgr.cancelAsUser(null, LOW_MEMORY_NOTIFICATION_ID, UserHandle.ALL);
- mContext.removeStickyBroadcastAsUser(mStorageLowIntent, UserHandle.ALL);
- mContext.sendBroadcastAsUser(mStorageOkIntent, UserHandle.ALL);
+ context.removeStickyBroadcastAsUser(mStorageLowIntent, UserHandle.ALL);
+ context.sendBroadcastAsUser(mStorageOkIntent, UserHandle.ALL);
}
/**
* Send a notification when storage is full.
*/
- private final void sendFullNotification() {
+ private void sendFullNotification() {
if(localLOGV) Slog.i(TAG, "Sending memory full notification");
- mContext.sendStickyBroadcastAsUser(mStorageFullIntent, UserHandle.ALL);
+ getContext().sendStickyBroadcastAsUser(mStorageFullIntent, UserHandle.ALL);
}
/**
* Cancels memory full notification and sends "not full" intent.
*/
- private final void cancelFullNotification() {
+ private void cancelFullNotification() {
if(localLOGV) Slog.i(TAG, "Canceling memory full notification");
- mContext.removeStickyBroadcastAsUser(mStorageFullIntent, UserHandle.ALL);
- mContext.sendBroadcastAsUser(mStorageNotFullIntent, UserHandle.ALL);
+ getContext().removeStickyBroadcastAsUser(mStorageFullIntent, UserHandle.ALL);
+ getContext().sendBroadcastAsUser(mStorageNotFullIntent, UserHandle.ALL);
}
- public void updateMemory() {
- int callingUid = getCallingUid();
- if(callingUid != Process.SYSTEM_UID) {
- return;
- }
- // force an early check
- postCheckMemoryMsg(true, 0);
- }
-
- /**
- * Callable from other things in the system service to obtain the low memory
- * threshold.
- *
- * @return low memory threshold in bytes
- */
- public long getMemoryLowThreshold() {
- return mMemLowThreshold;
- }
-
- /**
- * Callable from other things in the system process to check whether memory
- * is low.
- *
- * @return true is memory is low
- */
- public boolean isMemoryLow() {
- return mLowMemFlag;
- }
-
- public static class CacheFileDeletedObserver extends FileObserver {
+ private static class CacheFileDeletedObserver extends FileObserver {
public CacheFileDeletedObserver() {
super(Environment.getDownloadCacheDirectory().getAbsolutePath(), FileObserver.DELETE);
}
@@ -452,40 +502,4 @@
EventLogTags.writeCacheFileDeleted(path);
}
}
-
- @Override
- protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
-
- pw.println("Permission Denial: can't dump " + SERVICE + " from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
-
- pw.println("Current DeviceStorageMonitor state:");
- pw.print(" mFreeMem="); pw.print(Formatter.formatFileSize(mContext, mFreeMem));
- pw.print(" mTotalMemory=");
- pw.println(Formatter.formatFileSize(mContext, mTotalMemory));
- pw.print(" mFreeMemAfterLastCacheClear=");
- pw.println(Formatter.formatFileSize(mContext, mFreeMemAfterLastCacheClear));
- pw.print(" mLastReportedFreeMem=");
- pw.print(Formatter.formatFileSize(mContext, mLastReportedFreeMem));
- pw.print(" mLastReportedFreeMemTime=");
- TimeUtils.formatDuration(mLastReportedFreeMemTime, SystemClock.elapsedRealtime(), pw);
- pw.println();
- pw.print(" mLowMemFlag="); pw.print(mLowMemFlag);
- pw.print(" mMemFullFlag="); pw.println(mMemFullFlag);
- pw.print(" mClearSucceeded="); pw.print(mClearSucceeded);
- pw.print(" mClearingCache="); pw.println(mClearingCache);
- pw.print(" mMemLowThreshold=");
- pw.print(Formatter.formatFileSize(mContext, mMemLowThreshold));
- pw.print(" mMemFullThreshold=");
- pw.println(Formatter.formatFileSize(mContext, mMemFullThreshold));
- pw.print(" mMemCacheStartTrimThreshold=");
- pw.print(Formatter.formatFileSize(mContext, mMemCacheStartTrimThreshold));
- pw.print(" mMemCacheTrimToThreshold=");
- pw.println(Formatter.formatFileSize(mContext, mMemCacheTrimToThreshold));
- }
}
diff --git a/services/core/java/com/android/server/twilight/TwilightListener.java b/services/core/java/com/android/server/twilight/TwilightListener.java
new file mode 100644
index 0000000..29ead44
--- /dev/null
+++ b/services/core/java/com/android/server/twilight/TwilightListener.java
@@ -0,0 +1,21 @@
+/*
+ * 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.server.twilight;
+
+public interface TwilightListener {
+ void onTwilightStateChanged();
+}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/twilight/TwilightManager.java b/services/core/java/com/android/server/twilight/TwilightManager.java
new file mode 100644
index 0000000..b3de58b
--- /dev/null
+++ b/services/core/java/com/android/server/twilight/TwilightManager.java
@@ -0,0 +1,24 @@
+/*
+ * 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.server.twilight;
+
+import android.os.Handler;
+
+public interface TwilightManager {
+ void registerListener(TwilightListener listener, Handler handler);
+ TwilightState getCurrentState();
+}
diff --git a/services/java/com/android/server/TwilightService.java b/services/core/java/com/android/server/twilight/TwilightService.java
similarity index 74%
rename from services/java/com/android/server/TwilightService.java
rename to services/core/java/com/android/server/twilight/TwilightService.java
index 0356faa..8feb97b 100644
--- a/services/java/com/android/server/TwilightService.java
+++ b/services/core/java/com/android/server/twilight/TwilightService.java
@@ -14,7 +14,10 @@
* limitations under the License.
*/
-package com.android.server;
+package com.android.server.twilight;
+
+import com.android.server.SystemService;
+import com.android.server.TwilightCalculator;
import android.app.AlarmManager;
import android.app.PendingIntent;
@@ -34,9 +37,7 @@
import android.text.format.Time;
import android.util.Slog;
-import java.text.DateFormat;
import java.util.ArrayList;
-import java.util.Date;
import java.util.Iterator;
import libcore.util.Objects;
@@ -47,78 +48,88 @@
* Used by the UI mode manager and other components to adjust night mode
* effects based on sunrise and sunset.
*/
-public final class TwilightService {
- private static final String TAG = "TwilightService";
-
- private static final boolean DEBUG = false;
-
- private static final String ACTION_UPDATE_TWILIGHT_STATE =
+public final class TwilightService extends SystemService {
+ static final String TAG = "TwilightService";
+ static final boolean DEBUG = false;
+ static final String ACTION_UPDATE_TWILIGHT_STATE =
"com.android.server.action.UPDATE_TWILIGHT_STATE";
- private final Context mContext;
- private final AlarmManager mAlarmManager;
- private final LocationManager mLocationManager;
- private final LocationHandler mLocationHandler;
+ final Object mLock = new Object();
- private final Object mLock = new Object();
+ AlarmManager mAlarmManager;
+ LocationManager mLocationManager;
+ LocationHandler mLocationHandler;
- private final ArrayList<TwilightListenerRecord> mListeners =
+ final ArrayList<TwilightListenerRecord> mListeners =
new ArrayList<TwilightListenerRecord>();
- private boolean mSystemReady;
+ TwilightState mTwilightState;
- private TwilightState mTwilightState;
-
- public TwilightService(Context context) {
- mContext = context;
-
- mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
- mLocationManager = (LocationManager)mContext.getSystemService(Context.LOCATION_SERVICE);
+ @Override
+ public void onStart() {
+ mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
+ mLocationManager = (LocationManager) getContext().getSystemService(
+ Context.LOCATION_SERVICE);
mLocationHandler = new LocationHandler();
+
+ IntentFilter filter = new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+ filter.addAction(Intent.ACTION_TIME_CHANGED);
+ filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
+ filter.addAction(ACTION_UPDATE_TWILIGHT_STATE);
+ getContext().registerReceiver(mUpdateLocationReceiver, filter);
+
+ publishLocalService(TwilightManager.class, mService);
}
- void systemReady() {
- synchronized (mLock) {
- mSystemReady = true;
+ private static class TwilightListenerRecord implements Runnable {
+ private final TwilightListener mListener;
+ private final Handler mHandler;
- IntentFilter filter = new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);
- filter.addAction(Intent.ACTION_TIME_CHANGED);
- filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
- filter.addAction(ACTION_UPDATE_TWILIGHT_STATE);
- mContext.registerReceiver(mUpdateLocationReceiver, filter);
+ public TwilightListenerRecord(TwilightListener listener, Handler handler) {
+ mListener = listener;
+ mHandler = handler;
+ }
- if (!mListeners.isEmpty()) {
- mLocationHandler.enableLocationUpdates();
+ public void postUpdate() {
+ mHandler.post(this);
+ }
+
+ @Override
+ public void run() {
+ mListener.onTwilightStateChanged();
+ }
+
+ }
+
+ private final TwilightManager mService = new TwilightManager() {
+ /**
+ * Gets the current twilight state.
+ *
+ * @return The current twilight state, or null if no information is available.
+ */
+ @Override
+ public TwilightState getCurrentState() {
+ synchronized (mLock) {
+ return mTwilightState;
}
}
- }
- /**
- * Gets the current twilight state.
- *
- * @return The current twilight state, or null if no information is available.
- */
- public TwilightState getCurrentState() {
- synchronized (mLock) {
- return mTwilightState;
- }
- }
+ /**
+ * Listens for twilight time.
+ *
+ * @param listener The listener.
+ */
+ @Override
+ public void registerListener(TwilightListener listener, Handler handler) {
+ synchronized (mLock) {
+ mListeners.add(new TwilightListenerRecord(listener, handler));
- /**
- * Listens for twilight time.
- *
- * @param listener The listener.
- * @param handler The handler on which to post calls into the listener.
- */
- public void registerListener(TwilightListener listener, Handler handler) {
- synchronized (mLock) {
- mListeners.add(new TwilightListenerRecord(listener, handler));
-
- if (mSystemReady && mListeners.size() == 1) {
- mLocationHandler.enableLocationUpdates();
+ if (mListeners.size() == 1) {
+ mLocationHandler.enableLocationUpdates();
+ }
}
}
- }
+ };
private void setTwilightState(TwilightState state) {
synchronized (mLock) {
@@ -128,9 +139,10 @@
}
mTwilightState = state;
- int count = mListeners.size();
- for (int i = 0; i < count; i++) {
- mListeners.get(i).post();
+
+ final int listenerLen = mListeners.size();
+ for (int i = 0; i < listenerLen; i++) {
+ mListeners.get(i).postUpdate();
}
}
}
@@ -162,124 +174,6 @@
return distance >= totalAccuracy;
}
- /**
- * Describes whether it is day or night.
- * This object is immutable.
- */
- public static final class TwilightState {
- private final boolean mIsNight;
- private final long mYesterdaySunset;
- private final long mTodaySunrise;
- private final long mTodaySunset;
- private final long mTomorrowSunrise;
-
- TwilightState(boolean isNight,
- long yesterdaySunset,
- long todaySunrise, long todaySunset,
- long tomorrowSunrise) {
- mIsNight = isNight;
- mYesterdaySunset = yesterdaySunset;
- mTodaySunrise = todaySunrise;
- mTodaySunset = todaySunset;
- mTomorrowSunrise = tomorrowSunrise;
- }
-
- /**
- * Returns true if it is currently night time.
- */
- public boolean isNight() {
- return mIsNight;
- }
-
- /**
- * Returns the time of yesterday's sunset in the System.currentTimeMillis() timebase,
- * or -1 if the sun never sets.
- */
- public long getYesterdaySunset() {
- return mYesterdaySunset;
- }
-
- /**
- * Returns the time of today's sunrise in the System.currentTimeMillis() timebase,
- * or -1 if the sun never rises.
- */
- public long getTodaySunrise() {
- return mTodaySunrise;
- }
-
- /**
- * Returns the time of today's sunset in the System.currentTimeMillis() timebase,
- * or -1 if the sun never sets.
- */
- public long getTodaySunset() {
- return mTodaySunset;
- }
-
- /**
- * Returns the time of tomorrow's sunrise in the System.currentTimeMillis() timebase,
- * or -1 if the sun never rises.
- */
- public long getTomorrowSunrise() {
- return mTomorrowSunrise;
- }
-
- @Override
- public boolean equals(Object o) {
- return o instanceof TwilightState && equals((TwilightState)o);
- }
-
- public boolean equals(TwilightState other) {
- return other != null
- && mIsNight == other.mIsNight
- && mYesterdaySunset == other.mYesterdaySunset
- && mTodaySunrise == other.mTodaySunrise
- && mTodaySunset == other.mTodaySunset
- && mTomorrowSunrise == other.mTomorrowSunrise;
- }
-
- @Override
- public int hashCode() {
- return 0; // don't care
- }
-
- @Override
- public String toString() {
- DateFormat f = DateFormat.getDateTimeInstance();
- return "{TwilightState: isNight=" + mIsNight
- + ", mYesterdaySunset=" + f.format(new Date(mYesterdaySunset))
- + ", mTodaySunrise=" + f.format(new Date(mTodaySunrise))
- + ", mTodaySunset=" + f.format(new Date(mTodaySunset))
- + ", mTomorrowSunrise=" + f.format(new Date(mTomorrowSunrise))
- + "}";
- }
- }
-
- /**
- * Listener for changes in twilight state.
- */
- public interface TwilightListener {
- public void onTwilightStateChanged();
- }
-
- private static final class TwilightListenerRecord implements Runnable {
- private final TwilightListener mListener;
- private final Handler mHandler;
-
- public TwilightListenerRecord(TwilightListener listener, Handler handler) {
- mListener = listener;
- mHandler = handler;
- }
-
- public void post() {
- mHandler.post(this);
- }
-
- @Override
- public void run() {
- mListener.onTwilightStateChanged();
- }
- }
-
private final class LocationHandler extends Handler {
private static final int MSG_ENABLE_LOCATION_UPDATES = 1;
private static final int MSG_GET_NEW_LOCATION_UPDATE = 2;
@@ -518,11 +412,12 @@
}
Intent updateIntent = new Intent(ACTION_UPDATE_TWILIGHT_STATE);
- PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, updateIntent, 0);
+ PendingIntent pendingIntent = PendingIntent.getBroadcast(
+ getContext(), 0, updateIntent, 0);
mAlarmManager.cancel(pendingIntent);
mAlarmManager.setExact(AlarmManager.RTC, nextUpdate, pendingIntent);
}
- };
+ }
private final BroadcastReceiver mUpdateLocationReceiver = new BroadcastReceiver() {
@Override
diff --git a/services/core/java/com/android/server/twilight/TwilightState.java b/services/core/java/com/android/server/twilight/TwilightState.java
new file mode 100644
index 0000000..91e24d7
--- /dev/null
+++ b/services/core/java/com/android/server/twilight/TwilightState.java
@@ -0,0 +1,112 @@
+/*
+ * 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.server.twilight;
+
+import java.text.DateFormat;
+import java.util.Date;
+
+/**
+ * Describes whether it is day or night.
+ * This object is immutable.
+ */
+public class TwilightState {
+ private final boolean mIsNight;
+ private final long mYesterdaySunset;
+ private final long mTodaySunrise;
+ private final long mTodaySunset;
+ private final long mTomorrowSunrise;
+
+ TwilightState(boolean isNight,
+ long yesterdaySunset,
+ long todaySunrise, long todaySunset,
+ long tomorrowSunrise) {
+ mIsNight = isNight;
+ mYesterdaySunset = yesterdaySunset;
+ mTodaySunrise = todaySunrise;
+ mTodaySunset = todaySunset;
+ mTomorrowSunrise = tomorrowSunrise;
+ }
+
+ /**
+ * Returns true if it is currently night time.
+ */
+ public boolean isNight() {
+ return mIsNight;
+ }
+
+ /**
+ * Returns the time of yesterday's sunset in the System.currentTimeMillis() timebase,
+ * or -1 if the sun never sets.
+ */
+ public long getYesterdaySunset() {
+ return mYesterdaySunset;
+ }
+
+ /**
+ * Returns the time of today's sunrise in the System.currentTimeMillis() timebase,
+ * or -1 if the sun never rises.
+ */
+ public long getTodaySunrise() {
+ return mTodaySunrise;
+ }
+
+ /**
+ * Returns the time of today's sunset in the System.currentTimeMillis() timebase,
+ * or -1 if the sun never sets.
+ */
+ public long getTodaySunset() {
+ return mTodaySunset;
+ }
+
+ /**
+ * Returns the time of tomorrow's sunrise in the System.currentTimeMillis() timebase,
+ * or -1 if the sun never rises.
+ */
+ public long getTomorrowSunrise() {
+ return mTomorrowSunrise;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return o instanceof TwilightState && equals((TwilightState)o);
+ }
+
+ public boolean equals(TwilightState other) {
+ return other != null
+ && mIsNight == other.mIsNight
+ && mYesterdaySunset == other.mYesterdaySunset
+ && mTodaySunrise == other.mTodaySunrise
+ && mTodaySunset == other.mTodaySunset
+ && mTomorrowSunrise == other.mTomorrowSunrise;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0; // don't care
+ }
+
+ @Override
+ public String toString() {
+ DateFormat f = DateFormat.getDateTimeInstance();
+ return "{TwilightState: isNight=" + mIsNight
+ + ", mYesterdaySunset=" + f.format(new Date(mYesterdaySunset))
+ + ", mTodaySunrise=" + f.format(new Date(mTodaySunrise))
+ + ", mTodaySunset=" + f.format(new Date(mTodaySunset))
+ + ", mTomorrowSunrise=" + f.format(new Date(mTomorrowSunrise))
+ + "}";
+ }
+}
diff --git a/services/java/com/android/server/updates/CarrierProvisioningUrlsInstallReceiver.java b/services/core/java/com/android/server/updates/CarrierProvisioningUrlsInstallReceiver.java
similarity index 100%
rename from services/java/com/android/server/updates/CarrierProvisioningUrlsInstallReceiver.java
rename to services/core/java/com/android/server/updates/CarrierProvisioningUrlsInstallReceiver.java
diff --git a/services/java/com/android/server/updates/CertPinInstallReceiver.java b/services/core/java/com/android/server/updates/CertPinInstallReceiver.java
similarity index 100%
rename from services/java/com/android/server/updates/CertPinInstallReceiver.java
rename to services/core/java/com/android/server/updates/CertPinInstallReceiver.java
diff --git a/services/java/com/android/server/updates/ConfigUpdateInstallReceiver.java b/services/core/java/com/android/server/updates/ConfigUpdateInstallReceiver.java
similarity index 100%
rename from services/java/com/android/server/updates/ConfigUpdateInstallReceiver.java
rename to services/core/java/com/android/server/updates/ConfigUpdateInstallReceiver.java
diff --git a/services/java/com/android/server/updates/IntentFirewallInstallReceiver.java b/services/core/java/com/android/server/updates/IntentFirewallInstallReceiver.java
similarity index 100%
rename from services/java/com/android/server/updates/IntentFirewallInstallReceiver.java
rename to services/core/java/com/android/server/updates/IntentFirewallInstallReceiver.java
diff --git a/services/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java b/services/core/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java
similarity index 100%
rename from services/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java
rename to services/core/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java
diff --git a/services/java/com/android/server/updates/SmsShortCodesInstallReceiver.java b/services/core/java/com/android/server/updates/SmsShortCodesInstallReceiver.java
similarity index 100%
rename from services/java/com/android/server/updates/SmsShortCodesInstallReceiver.java
rename to services/core/java/com/android/server/updates/SmsShortCodesInstallReceiver.java
diff --git a/services/java/com/android/server/updates/TZInfoInstallReceiver.java b/services/core/java/com/android/server/updates/TZInfoInstallReceiver.java
similarity index 100%
rename from services/java/com/android/server/updates/TZInfoInstallReceiver.java
rename to services/core/java/com/android/server/updates/TZInfoInstallReceiver.java
diff --git a/services/java/com/android/server/usb/UsbDebuggingManager.java b/services/core/java/com/android/server/usb/UsbDebuggingManager.java
similarity index 100%
rename from services/java/com/android/server/usb/UsbDebuggingManager.java
rename to services/core/java/com/android/server/usb/UsbDebuggingManager.java
diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/core/java/com/android/server/usb/UsbDeviceManager.java
similarity index 100%
rename from services/java/com/android/server/usb/UsbDeviceManager.java
rename to services/core/java/com/android/server/usb/UsbDeviceManager.java
diff --git a/services/java/com/android/server/usb/UsbHostManager.java b/services/core/java/com/android/server/usb/UsbHostManager.java
similarity index 100%
rename from services/java/com/android/server/usb/UsbHostManager.java
rename to services/core/java/com/android/server/usb/UsbHostManager.java
diff --git a/services/java/com/android/server/usb/UsbService.java b/services/core/java/com/android/server/usb/UsbService.java
similarity index 100%
rename from services/java/com/android/server/usb/UsbService.java
rename to services/core/java/com/android/server/usb/UsbService.java
diff --git a/services/java/com/android/server/usb/UsbSettingsManager.java b/services/core/java/com/android/server/usb/UsbSettingsManager.java
similarity index 100%
rename from services/java/com/android/server/usb/UsbSettingsManager.java
rename to services/core/java/com/android/server/usb/UsbSettingsManager.java
diff --git a/services/java/com/android/server/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
similarity index 98%
rename from services/java/com/android/server/WallpaperManagerService.java
rename to services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index e6b6b93..97ea52c 100644
--- a/services/java/com/android/server/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server;
+package com.android.server.wallpaper;
import static android.os.ParcelFileDescriptor.*;
@@ -85,8 +85,8 @@
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.JournaledFile;
-class WallpaperManagerService extends IWallpaperManager.Stub {
- static final String TAG = "WallpaperService";
+public class WallpaperManagerService extends IWallpaperManager.Stub {
+ static final String TAG = "WallpaperManagerService";
static final boolean DEBUG = false;
final Object mLock = new Object[0];
@@ -98,7 +98,6 @@
static final long MIN_WALLPAPER_CRASH_TIME = 10000;
static final String WALLPAPER = "wallpaper";
static final String WALLPAPER_INFO = "wallpaper_info.xml";
-
/**
* Name of the component used to display bitmap wallpapers from either the gallery or
* built-in wallpapers.
@@ -505,7 +504,12 @@
}
}
- String getName() {
+ /** Called by SystemBackupAgent */
+ public String getName() {
+ // Verify caller is the system
+ if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
+ throw new RuntimeException("getName() can only be called from the system process");
+ }
synchronized (mLock) {
return mWallpaperMap.get(0).name;
}
@@ -1175,7 +1179,11 @@
}
// Called by SystemBackupAgent after files are restored to disk.
- void settingsRestored() {
+ public void settingsRestored() {
+ // Verify caller is the system
+ if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
+ throw new RuntimeException("settingsRestored() can only be called from the system process");
+ }
// TODO: If necessary, make it work for secondary users as well. This currently assumes
// restores only to the primary user
if (DEBUG) Slog.v(TAG, "settingsRestored");
diff --git a/services/java/com/android/server/wifi/README.txt b/services/core/java/com/android/server/wifi/README.txt
similarity index 100%
rename from services/java/com/android/server/wifi/README.txt
rename to services/core/java/com/android/server/wifi/README.txt
diff --git a/services/java/com/android/server/wifi/WifiController.java b/services/core/java/com/android/server/wifi/WifiController.java
similarity index 100%
rename from services/java/com/android/server/wifi/WifiController.java
rename to services/core/java/com/android/server/wifi/WifiController.java
diff --git a/services/java/com/android/server/wifi/WifiNotificationController.java b/services/core/java/com/android/server/wifi/WifiNotificationController.java
similarity index 100%
rename from services/java/com/android/server/wifi/WifiNotificationController.java
rename to services/core/java/com/android/server/wifi/WifiNotificationController.java
diff --git a/services/java/com/android/server/wifi/WifiService.java b/services/core/java/com/android/server/wifi/WifiService.java
similarity index 100%
rename from services/java/com/android/server/wifi/WifiService.java
rename to services/core/java/com/android/server/wifi/WifiService.java
diff --git a/services/java/com/android/server/wifi/WifiSettingsStore.java b/services/core/java/com/android/server/wifi/WifiSettingsStore.java
similarity index 100%
rename from services/java/com/android/server/wifi/WifiSettingsStore.java
rename to services/core/java/com/android/server/wifi/WifiSettingsStore.java
diff --git a/services/java/com/android/server/wifi/WifiTrafficPoller.java b/services/core/java/com/android/server/wifi/WifiTrafficPoller.java
similarity index 100%
rename from services/java/com/android/server/wifi/WifiTrafficPoller.java
rename to services/core/java/com/android/server/wifi/WifiTrafficPoller.java
diff --git a/services/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
similarity index 100%
rename from services/java/com/android/server/wm/AppTransition.java
rename to services/core/java/com/android/server/wm/AppTransition.java
diff --git a/services/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java
similarity index 100%
rename from services/java/com/android/server/wm/AppWindowAnimator.java
rename to services/core/java/com/android/server/wm/AppWindowAnimator.java
diff --git a/services/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
similarity index 100%
rename from services/java/com/android/server/wm/AppWindowToken.java
rename to services/core/java/com/android/server/wm/AppWindowToken.java
diff --git a/services/java/com/android/server/wm/BlackFrame.java b/services/core/java/com/android/server/wm/BlackFrame.java
similarity index 100%
rename from services/java/com/android/server/wm/BlackFrame.java
rename to services/core/java/com/android/server/wm/BlackFrame.java
diff --git a/services/java/com/android/server/wm/DimLayer.java b/services/core/java/com/android/server/wm/DimLayer.java
similarity index 99%
rename from services/java/com/android/server/wm/DimLayer.java
rename to services/core/java/com/android/server/wm/DimLayer.java
index c189ddd..978d5b7 100644
--- a/services/java/com/android/server/wm/DimLayer.java
+++ b/services/core/java/com/android/server/wm/DimLayer.java
@@ -166,7 +166,7 @@
final int dw, dh;
final float xPos, yPos;
- if (mStack.hasSibling()) {
+ if (!mStack.isFullscreen()) {
dw = mBounds.width();
dh = mBounds.height();
xPos = mBounds.left;
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
new file mode 100644
index 0000000..0a070c1
--- /dev/null
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -0,0 +1,441 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
+import static com.android.server.wm.WindowManagerService.DEBUG_STACK;
+import static com.android.server.wm.WindowManagerService.DEBUG_VISIBILITY;
+import static com.android.server.wm.WindowManagerService.TAG;
+
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.util.EventLog;
+import android.util.Slog;
+import android.view.Display;
+import android.view.DisplayInfo;
+import android.view.Surface;
+import com.android.server.EventLogTags;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+class DisplayContentList extends ArrayList<DisplayContent> {
+}
+
+/**
+ * Utility class for keeping track of the WindowStates and other pertinent contents of a
+ * particular Display.
+ *
+ * IMPORTANT: No method from this class should ever be used without holding
+ * WindowManagerService.mWindowMap.
+ */
+class DisplayContent {
+
+ /** Unique identifier of this stack. */
+ private final int mDisplayId;
+
+ /** Z-ordered (bottom-most first) list of all Window objects. Assigned to an element
+ * from mDisplayWindows; */
+ private WindowList mWindows = new WindowList();
+
+ // This protects the following display size properties, so that
+ // getDisplaySize() doesn't need to acquire the global lock. This is
+ // needed because the window manager sometimes needs to use ActivityThread
+ // while it has its global state locked (for example to load animation
+ // resources), but the ActivityThread also needs get the current display
+ // size sometimes when it has its package lock held.
+ //
+ // These will only be modified with both mWindowMap and mDisplaySizeLock
+ // held (in that order) so the window manager doesn't need to acquire this
+ // lock when needing these values in its normal operation.
+ final Object mDisplaySizeLock = new Object();
+ int mInitialDisplayWidth = 0;
+ int mInitialDisplayHeight = 0;
+ int mInitialDisplayDensity = 0;
+ int mBaseDisplayWidth = 0;
+ int mBaseDisplayHeight = 0;
+ int mBaseDisplayDensity = 0;
+ private final DisplayInfo mDisplayInfo = new DisplayInfo();
+ private final Display mDisplay;
+
+ Rect mBaseDisplayRect = new Rect();
+ Rect mContentRect = new Rect();
+
+ // Accessed directly by all users.
+ boolean layoutNeeded;
+ int pendingLayoutChanges;
+ final boolean isDefaultDisplay;
+
+ /**
+ * Window tokens that are in the process of exiting, but still
+ * on screen for animations.
+ */
+ final ArrayList<WindowToken> mExitingTokens = new ArrayList<WindowToken>();
+
+ /**
+ * Application tokens that are in the process of exiting, but still
+ * on screen for animations.
+ */
+ final AppTokenList mExitingAppTokens = new AppTokenList();
+
+ /** Array containing all TaskStacks on this display. Array
+ * is stored in display order with the current bottom stack at 0. */
+ private ArrayList<TaskStack> mStacks = new ArrayList<TaskStack>();
+
+ /** A special TaskStack with id==HOME_STACK_ID that moves to the bottom whenever any TaskStack
+ * (except a future lockscreen TaskStack) moves to the top. */
+ private TaskStack mHomeStack = null;
+
+ /** Detect user tapping outside of current focused stack bounds .*/
+ StackTapPointerEventListener mTapDetector;
+
+ /** Detect user tapping outside of current focused stack bounds .*/
+ Region mTouchExcludeRegion = new Region();
+
+ /** Save allocating when retrieving tasks */
+ private ArrayList<Task> mTaskHistory = new ArrayList<Task>();
+
+ /** Save allocating when calculating rects */
+ Rect mTmpRect = new Rect();
+
+ final WindowManagerService mService;
+
+ /**
+ * @param display May not be null.
+ * @param service TODO(cmautner):
+ */
+ DisplayContent(Display display, WindowManagerService service) {
+ mDisplay = display;
+ mDisplayId = display.getDisplayId();
+ display.getDisplayInfo(mDisplayInfo);
+ isDefaultDisplay = mDisplayId == Display.DEFAULT_DISPLAY;
+ mService = service;
+ }
+
+ int getDisplayId() {
+ return mDisplayId;
+ }
+
+ WindowList getWindowList() {
+ return mWindows;
+ }
+
+ Display getDisplay() {
+ return mDisplay;
+ }
+
+ DisplayInfo getDisplayInfo() {
+ return mDisplayInfo;
+ }
+
+ /**
+ * Returns true if the specified UID has access to this display.
+ */
+ public boolean hasAccess(int uid) {
+ return mDisplay.hasAccess(uid);
+ }
+
+ public boolean isPrivate() {
+ return (mDisplay.getFlags() & Display.FLAG_PRIVATE) != 0;
+ }
+
+ /**
+ * Retrieve the tasks on this display in stack order from the bottommost TaskStack up.
+ * @return All the Tasks, in order, on this display.
+ */
+ ArrayList<Task> getTasks() {
+ return mTaskHistory;
+ }
+
+ void addTask(Task task, boolean toTop) {
+ mTaskHistory.remove(task);
+
+ final int userId = task.mUserId;
+ int taskNdx;
+ final int numTasks = mTaskHistory.size();
+ if (toTop) {
+ for (taskNdx = numTasks - 1; taskNdx >= 0; --taskNdx) {
+ if (mTaskHistory.get(taskNdx).mUserId == userId) {
+ break;
+ }
+ }
+ ++taskNdx;
+ } else {
+ for (taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
+ if (mTaskHistory.get(taskNdx).mUserId == userId) {
+ break;
+ }
+ }
+ }
+
+ mTaskHistory.add(taskNdx, task);
+ EventLog.writeEvent(EventLogTags.WM_TASK_MOVED, task.taskId, toTop ? 1 : 0, taskNdx);
+ }
+
+ void removeTask(Task task) {
+ mTaskHistory.remove(task);
+ }
+
+ TaskStack getHomeStack() {
+ if (mHomeStack == null) {
+ Slog.e(TAG, "getHomeStack: Returning null from this=" + this);
+ }
+ return mHomeStack;
+ }
+
+ void updateDisplayInfo() {
+ // Save old size.
+ int oldWidth = mDisplayInfo.logicalWidth;
+ int oldHeight = mDisplayInfo.logicalHeight;
+ mDisplay.getDisplayInfo(mDisplayInfo);
+
+ for (int i = mStacks.size() - 1; i >= 0; --i) {
+ final TaskStack stack = mStacks.get(i);
+ if (!stack.isFullscreen()) {
+ stack.resizeBounds(oldWidth, oldHeight, mDisplayInfo.logicalWidth,
+ mDisplayInfo.logicalHeight);
+ }
+ }
+ }
+
+ void getLogicalDisplayRect(Rect out) {
+ updateDisplayInfo();
+ // Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked.
+ final int orientation = mDisplayInfo.rotation;
+ boolean rotated = (orientation == Surface.ROTATION_90
+ || orientation == Surface.ROTATION_270);
+ final int physWidth = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;
+ final int physHeight = rotated ? mBaseDisplayWidth : mBaseDisplayHeight;
+ int width = mDisplayInfo.logicalWidth;
+ int left = (physWidth - width) / 2;
+ int height = mDisplayInfo.logicalHeight;
+ int top = (physHeight - height) / 2;
+ out.set(left, top, left + width, top + height);
+ }
+
+ /** @return The number of tokens in all of the Tasks on this display. */
+ int numTokens() {
+ int count = 0;
+ for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
+ count += mTaskHistory.get(taskNdx).mAppTokens.size();
+ }
+ return count;
+ }
+
+ /** Refer to {@link WindowManagerService#createStack(int, int)} */
+ TaskStack createStack(int stackId) {
+ if (DEBUG_STACK) Slog.d(TAG, "createStack: stackId=" + stackId);
+ TaskStack newStack = new TaskStack(mService, stackId, this);
+ if (stackId == HOME_STACK_ID) {
+ if (mHomeStack != null) {
+ throw new IllegalArgumentException("createStack: HOME_STACK_ID (0) not first.");
+ }
+ mHomeStack = newStack;
+ }
+ mStacks.add(newStack);
+ layoutNeeded = true;
+ return newStack;
+ }
+
+ void moveStack(TaskStack stack, boolean toTop) {
+ mStacks.remove(stack);
+ mStacks.add(toTop ? mStacks.size() : 0, stack);
+ }
+
+ TaskStack removeStack(TaskStack stack) {
+ mStacks.remove(stack);
+ if (!mStacks.isEmpty()) {
+ return mStacks.get(mStacks.size() - 1);
+ }
+ return null;
+ }
+
+ /**
+ * Propagate the new bounds to all child stacks.
+ * @param contentRect The bounds to apply at the top level.
+ */
+ void resize(Rect contentRect) {
+ mContentRect.set(contentRect);
+ }
+
+ boolean getStackBounds(int stackId, Rect bounds) {
+ for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final TaskStack stack = mStacks.get(stackNdx);
+ if (stackId == stack.mStackId) {
+ bounds.set(stack.mBounds);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ int stackIdFromPoint(int x, int y) {
+ for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final TaskStack stack = mStacks.get(stackNdx);
+ stack.getBounds(mTmpRect);
+ if (mTmpRect.contains(x, y)) {
+ return stack.mStackId;
+ }
+ }
+ return -1;
+ }
+
+ void setTouchExcludeRegion(TaskStack focusedStack) {
+ mTouchExcludeRegion.set(mBaseDisplayRect);
+ WindowList windows = getWindowList();
+ for (int i = windows.size() - 1; i >= 0; --i) {
+ final WindowState win = windows.get(i);
+ final TaskStack stack = win.getStack();
+ if (win.isVisibleLw() && stack != null && stack != focusedStack) {
+ mTmpRect.set(win.mVisibleFrame);
+ mTmpRect.intersect(win.mVisibleInsets);
+ mTouchExcludeRegion.op(mTmpRect, Region.Op.DIFFERENCE);
+ }
+ }
+ }
+
+ void switchUserStacks(int oldUserId, int newUserId) {
+ final WindowList windows = getWindowList();
+ for (int i = 0; i < windows.size(); i++) {
+ final WindowState win = windows.get(i);
+ if (win.isHiddenFromUserLocked()) {
+ if (DEBUG_VISIBILITY) Slog.w(TAG, "user changing " + newUserId + " hiding "
+ + win + ", attrs=" + win.mAttrs.type + ", belonging to "
+ + win.mOwnerUid);
+ win.hideLw(false);
+ }
+ }
+
+ for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ mStacks.get(stackNdx).switchUser(newUserId);
+ }
+ }
+
+ void resetAnimationBackgroundAnimator() {
+ for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ mStacks.get(stackNdx).resetAnimationBackgroundAnimator();
+ }
+ }
+
+ boolean animateDimLayers() {
+ boolean result = false;
+ for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ result |= mStacks.get(stackNdx).animateDimLayers();
+ }
+ return result;
+ }
+
+ void resetDimming() {
+ for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ mStacks.get(stackNdx).resetDimmingTag();
+ }
+ }
+
+ boolean isDimming() {
+ boolean result = false;
+ for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ result |= mStacks.get(stackNdx).isDimming();
+ }
+ return result;
+ }
+
+ void stopDimmingIfNeeded() {
+ for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ mStacks.get(stackNdx).stopDimmingIfNeeded();
+ }
+ }
+
+ void close() {
+ for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ mStacks.get(stackNdx).close();
+ }
+ }
+
+ public void dump(String prefix, PrintWriter pw) {
+ pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId);
+ final String subPrefix = " " + prefix;
+ pw.print(subPrefix); pw.print("init="); pw.print(mInitialDisplayWidth); pw.print("x");
+ pw.print(mInitialDisplayHeight); pw.print(" "); pw.print(mInitialDisplayDensity);
+ pw.print("dpi");
+ if (mInitialDisplayWidth != mBaseDisplayWidth
+ || mInitialDisplayHeight != mBaseDisplayHeight
+ || mInitialDisplayDensity != mBaseDisplayDensity) {
+ pw.print(" base=");
+ pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight);
+ pw.print(" "); pw.print(mBaseDisplayDensity); pw.print("dpi");
+ }
+ pw.print(" cur=");
+ pw.print(mDisplayInfo.logicalWidth);
+ pw.print("x"); pw.print(mDisplayInfo.logicalHeight);
+ pw.print(" app=");
+ pw.print(mDisplayInfo.appWidth);
+ pw.print("x"); pw.print(mDisplayInfo.appHeight);
+ pw.print(" rng="); pw.print(mDisplayInfo.smallestNominalAppWidth);
+ pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight);
+ pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth);
+ pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight);
+ pw.print(subPrefix); pw.print("layoutNeeded="); pw.println(layoutNeeded);
+ for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final TaskStack stack = mStacks.get(stackNdx);
+ pw.print(prefix); pw.print("mStacks[" + stackNdx + "]"); pw.println(stack.mStackId);
+ stack.dump(prefix + " ", pw);
+ }
+ int ndx = numTokens();
+ if (ndx > 0) {
+ pw.println();
+ pw.println(" Application tokens in Z order:");
+ getTasks();
+ for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
+ AppTokenList tokens = mTaskHistory.get(taskNdx).mAppTokens;
+ for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
+ final AppWindowToken wtoken = tokens.get(tokenNdx);
+ pw.print(" App #"); pw.print(ndx--);
+ pw.print(' '); pw.print(wtoken); pw.println(":");
+ wtoken.dump(pw, " ");
+ }
+ }
+ }
+ if (mExitingTokens.size() > 0) {
+ pw.println();
+ pw.println(" Exiting tokens:");
+ for (int i=mExitingTokens.size()-1; i>=0; i--) {
+ WindowToken token = mExitingTokens.get(i);
+ pw.print(" Exiting #"); pw.print(i);
+ pw.print(' '); pw.print(token);
+ pw.println(':');
+ token.dump(pw, " ");
+ }
+ }
+ if (mExitingAppTokens.size() > 0) {
+ pw.println();
+ pw.println(" Exiting application tokens:");
+ for (int i=mExitingAppTokens.size()-1; i>=0; i--) {
+ WindowToken token = mExitingAppTokens.get(i);
+ pw.print(" Exiting App #"); pw.print(i);
+ pw.print(' '); pw.print(token);
+ pw.println(':');
+ token.dump(pw, " ");
+ }
+ }
+ pw.println();
+ }
+
+ @Override
+ public String toString() {
+ return "Display " + mDisplayId + " info=" + mDisplayInfo + " stacks=" + mStacks;
+ }
+}
diff --git a/services/java/com/android/server/wm/DisplayMagnifier.java b/services/core/java/com/android/server/wm/DisplayMagnifier.java
similarity index 100%
rename from services/java/com/android/server/wm/DisplayMagnifier.java
rename to services/core/java/com/android/server/wm/DisplayMagnifier.java
diff --git a/services/java/com/android/server/wm/DisplaySettings.java b/services/core/java/com/android/server/wm/DisplaySettings.java
similarity index 100%
rename from services/java/com/android/server/wm/DisplaySettings.java
rename to services/core/java/com/android/server/wm/DisplaySettings.java
diff --git a/services/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
similarity index 100%
rename from services/java/com/android/server/wm/DragState.java
rename to services/core/java/com/android/server/wm/DragState.java
diff --git a/services/java/com/android/server/wm/FakeWindowImpl.java b/services/core/java/com/android/server/wm/FakeWindowImpl.java
similarity index 100%
rename from services/java/com/android/server/wm/FakeWindowImpl.java
rename to services/core/java/com/android/server/wm/FakeWindowImpl.java
diff --git a/services/java/com/android/server/wm/FocusedStackFrame.java b/services/core/java/com/android/server/wm/FocusedStackFrame.java
similarity index 97%
rename from services/java/com/android/server/wm/FocusedStackFrame.java
rename to services/core/java/com/android/server/wm/FocusedStackFrame.java
index cc48b86..f1f5fe8 100644
--- a/services/java/com/android/server/wm/FocusedStackFrame.java
+++ b/services/core/java/com/android/server/wm/FocusedStackFrame.java
@@ -41,7 +41,7 @@
private final SurfaceControl mSurfaceControl;
private final Surface mSurface = new Surface();
private final Rect mLastBounds = new Rect();
- private final Rect mBounds = new Rect();
+ final Rect mBounds = new Rect();
private final Rect mTmpDrawRect = new Rect();
public FocusedStackFrame(Display display, SurfaceSession session) {
@@ -131,9 +131,9 @@
}
}
- public void setBounds(Rect bounds) {
- if (false && DEBUG_STACK) Slog.i(TAG, "setBounds: bounds=" + bounds);
- mBounds.set(bounds);
+ public void setBounds(TaskStack stack) {
+ stack.getBounds(mBounds);
+ if (false && DEBUG_STACK) Slog.i(TAG, "setBounds: bounds=" + mBounds);
}
public void setLayer(int layer) {
diff --git a/services/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
similarity index 99%
rename from services/java/com/android/server/wm/InputMonitor.java
rename to services/core/java/com/android/server/wm/InputMonitor.java
index 3d2ec45..803b9ac 100644
--- a/services/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -58,6 +58,8 @@
private final Object mInputDevicesReadyMonitor = new Object();
private boolean mInputDevicesReady;
+ Rect mTmpRect = new Rect();
+
public InputMonitor(WindowManagerService service) {
mService = service;
}
@@ -175,7 +177,8 @@
if (modal && child.mAppToken != null) {
// Limit the outer touch to the activity stack region.
flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
- inputWindowHandle.touchableRegion.set(child.getStackBounds());
+ child.getStackBounds(mTmpRect);
+ inputWindowHandle.touchableRegion.set(mTmpRect);
} else {
// Not modal or full screen modal
child.getTouchableRegion(inputWindowHandle.touchableRegion);
diff --git a/services/java/com/android/server/wm/KeyguardDisableHandler.java b/services/core/java/com/android/server/wm/KeyguardDisableHandler.java
similarity index 100%
rename from services/java/com/android/server/wm/KeyguardDisableHandler.java
rename to services/core/java/com/android/server/wm/KeyguardDisableHandler.java
diff --git a/services/java/com/android/server/wm/PointerEventDispatcher.java b/services/core/java/com/android/server/wm/PointerEventDispatcher.java
similarity index 100%
rename from services/java/com/android/server/wm/PointerEventDispatcher.java
rename to services/core/java/com/android/server/wm/PointerEventDispatcher.java
diff --git a/services/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
similarity index 100%
rename from services/java/com/android/server/wm/ScreenRotationAnimation.java
rename to services/core/java/com/android/server/wm/ScreenRotationAnimation.java
diff --git a/services/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
similarity index 100%
rename from services/java/com/android/server/wm/Session.java
rename to services/core/java/com/android/server/wm/Session.java
diff --git a/services/java/com/android/server/wm/StackTapPointerEventListener.java b/services/core/java/com/android/server/wm/StackTapPointerEventListener.java
similarity index 100%
rename from services/java/com/android/server/wm/StackTapPointerEventListener.java
rename to services/core/java/com/android/server/wm/StackTapPointerEventListener.java
diff --git a/services/java/com/android/server/wm/StartingData.java b/services/core/java/com/android/server/wm/StartingData.java
similarity index 100%
rename from services/java/com/android/server/wm/StartingData.java
rename to services/core/java/com/android/server/wm/StartingData.java
diff --git a/services/java/com/android/server/wm/StrictModeFlash.java b/services/core/java/com/android/server/wm/StrictModeFlash.java
similarity index 100%
rename from services/java/com/android/server/wm/StrictModeFlash.java
rename to services/core/java/com/android/server/wm/StrictModeFlash.java
diff --git a/services/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
similarity index 100%
rename from services/java/com/android/server/wm/Task.java
rename to services/core/java/com/android/server/wm/Task.java
diff --git a/services/java/com/android/server/wm/TaskGroup.java b/services/core/java/com/android/server/wm/TaskGroup.java
similarity index 100%
rename from services/java/com/android/server/wm/TaskGroup.java
rename to services/core/java/com/android/server/wm/TaskGroup.java
diff --git a/services/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
similarity index 82%
rename from services/java/com/android/server/wm/TaskStack.java
rename to services/core/java/com/android/server/wm/TaskStack.java
index cb29df4..aa6b0c9 100644
--- a/services/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -26,8 +26,6 @@
import android.util.TypedValue;
import com.android.server.EventLogTags;
-import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
-
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -49,8 +47,9 @@
* mTaskHistory in the ActivityStack with the same mStackId */
private final ArrayList<Task> mTasks = new ArrayList<Task>();
- /** The StackBox this sits in. */
- StackBox mStackBox;
+ /** Content limits relative to the DisplayContent this sits in. Empty indicates fullscreen,
+ * Nonempty is size of this TaskStack but is also used to scale if DisplayContent changes. */
+ Rect mBounds = new Rect();
/** Used to support {@link android.view.WindowManager.LayoutParams#FLAG_DIM_BEHIND} */
final DimLayer mDimLayer;
@@ -74,6 +73,9 @@
mDisplayContent = displayContent;
mDimLayer = new DimLayer(service, this);
mAnimationBackgroundSurface = new DimLayer(service, this);
+ // TODO: remove bounds from log, they are always 0.
+ EventLog.writeEvent(EventLogTags.WM_STACK_CREATED, stackId, mBounds.left, mBounds.top,
+ mBounds.right, mBounds.bottom);
}
DisplayContent getDisplayContent() {
@@ -84,12 +86,64 @@
return mTasks;
}
- boolean isHomeStack() {
- return mStackId == HOME_STACK_ID;
+ private void resizeWindows() {
+ final boolean underStatusBar = mBounds.top == 0;
+
+ final ArrayList<WindowState> resizingWindows = mService.mResizingWindows;
+ for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
+ final ArrayList<AppWindowToken> activities = mTasks.get(taskNdx).mAppTokens;
+ for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
+ final ArrayList<WindowState> windows = activities.get(activityNdx).allAppWindows;
+ for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
+ final WindowState win = windows.get(winNdx);
+ if (!resizingWindows.contains(win)) {
+ if (WindowManagerService.DEBUG_RESIZE) Slog.d(TAG,
+ "setBounds: Resizing " + win);
+ resizingWindows.add(win);
+ }
+ win.mUnderStatusBar = underStatusBar;
+ }
+ }
+ }
}
- boolean hasSibling() {
- return mStackBox.mParent != null;
+ boolean setBounds(Rect bounds) {
+ if (mBounds.equals(bounds)) {
+ return false;
+ }
+
+ mDimLayer.setBounds(bounds);
+ mAnimationBackgroundSurface.setBounds(bounds);
+ mBounds.set(bounds);
+
+ resizeWindows();
+ return true;
+ }
+
+ void getBounds(Rect out) {
+ if (mBounds.isEmpty()) {
+ mDisplayContent.getLogicalDisplayRect(out);
+ } else {
+ out.set(mBounds);
+ }
+ out.intersect(mDisplayContent.mContentRect);
+ }
+
+ boolean isFullscreen() {
+ return mBounds.isEmpty();
+ }
+
+ void resizeBounds(float oldWidth, float oldHeight, float newWidth, float newHeight) {
+ if (oldWidth == newWidth && oldHeight == newHeight) {
+ return;
+ }
+ float widthScale = newWidth / oldWidth;
+ float heightScale = newHeight / oldHeight;
+ mBounds.left = (int)(mBounds.left * widthScale + 0.5);
+ mBounds.top = (int)(mBounds.top * heightScale + 0.5);
+ mBounds.right = (int)(mBounds.right * widthScale + 0.5);
+ mBounds.bottom = (int)(mBounds.bottom * heightScale + 0.5);
+ resizeWindows();
}
/**
@@ -97,9 +151,7 @@
* @param task The task to add.
* @param toTop Whether to add it to the top or bottom.
*/
- boolean addTask(Task task, boolean toTop) {
- mStackBox.makeDirty();
-
+ void addTask(Task task, boolean toTop) {
int stackNdx;
if (!toTop) {
stackNdx = 0;
@@ -122,39 +174,46 @@
task.mStack = this;
mDisplayContent.addTask(task, toTop);
- return mDisplayContent.moveHomeStackBox(mStackId == HOME_STACK_ID);
+ mDisplayContent.moveStack(this, true);
}
- boolean moveTaskToTop(Task task) {
+ void moveTaskToTop(Task task) {
if (DEBUG_TASK_MOVEMENT) Slog.d(TAG, "moveTaskToTop: task=" + task + " Callers="
+ Debug.getCallers(6));
mTasks.remove(task);
- return addTask(task, true);
+ addTask(task, true);
}
- boolean moveTaskToBottom(Task task) {
+ void moveTaskToBottom(Task task) {
if (DEBUG_TASK_MOVEMENT) Slog.d(TAG, "moveTaskToBottom: task=" + task);
mTasks.remove(task);
- return addTask(task, false);
+ addTask(task, false);
}
/**
- * Delete a Task from this stack. If it is the last Task in the stack, remove this stack from
- * its parent StackBox and merge the parent.
+ * Delete a Task from this stack. If it is the last Task in the stack, move this stack to the
+ * back.
* @param task The Task to delete.
*/
void removeTask(Task task) {
if (DEBUG_TASK_MOVEMENT) Slog.d(TAG, "removeTask: task=" + task);
- mStackBox.makeDirty();
mTasks.remove(task);
mDisplayContent.removeTask(task);
+ if (mTasks.isEmpty()) {
+ mDisplayContent.moveStack(this, false);
+ }
+ mDisplayContent.layoutNeeded = true;
}
int remove() {
mAnimationBackgroundSurface.destroySurface();
mDimLayer.destroySurface();
EventLog.writeEvent(EventLogTags.WM_STACK_REMOVED, mStackId);
- return mStackBox.remove();
+ TaskStack next = mDisplayContent.removeStack(this);
+ if (next != null) {
+ return next.mStackId;
+ }
+ return -1;
}
void resetAnimationBackgroundAnimator() {
@@ -259,28 +318,6 @@
}
}
- void setBounds(Rect bounds, boolean underStatusBar) {
- mDimLayer.setBounds(bounds);
- mAnimationBackgroundSurface.setBounds(bounds);
-
- final ArrayList<WindowState> resizingWindows = mService.mResizingWindows;
- for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
- final ArrayList<AppWindowToken> activities = mTasks.get(taskNdx).mAppTokens;
- for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
- final ArrayList<WindowState> windows = activities.get(activityNdx).allAppWindows;
- for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
- final WindowState win = windows.get(winNdx);
- if (!resizingWindows.contains(win)) {
- if (WindowManagerService.DEBUG_RESIZE) Slog.d(TAG,
- "setBounds: Resizing " + win);
- resizingWindows.add(win);
- }
- win.mUnderStatusBar = underStatusBar;
- }
- }
- }
- }
-
void switchUser(int userId) {
int top = mTasks.size();
for (int taskNdx = 0; taskNdx < top; ++taskNdx) {
@@ -293,6 +330,11 @@
}
}
+ void close() {
+ mDimLayer.mDimSurface.destroy();
+ mAnimationBackgroundSurface.mDimSurface.destroy();
+ }
+
public void dump(String prefix, PrintWriter pw) {
pw.print(prefix); pw.print("mStackId="); pw.println(mStackId);
for (int taskNdx = 0; taskNdx < mTasks.size(); ++taskNdx) {
diff --git a/services/java/com/android/server/wm/ViewServer.java b/services/core/java/com/android/server/wm/ViewServer.java
similarity index 100%
rename from services/java/com/android/server/wm/ViewServer.java
rename to services/core/java/com/android/server/wm/ViewServer.java
diff --git a/services/java/com/android/server/wm/Watermark.java b/services/core/java/com/android/server/wm/Watermark.java
similarity index 100%
rename from services/java/com/android/server/wm/Watermark.java
rename to services/core/java/com/android/server/wm/Watermark.java
diff --git a/services/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
similarity index 100%
rename from services/java/com/android/server/wm/WindowAnimator.java
rename to services/core/java/com/android/server/wm/WindowAnimator.java
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
similarity index 98%
rename from services/java/com/android/server/wm/WindowManagerService.java
rename to services/core/java/com/android/server/wm/WindowManagerService.java
index f9773a6..59134f9 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -18,8 +18,6 @@
import static android.view.WindowManager.LayoutParams.*;
-import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
-
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import android.app.AppOpsManager;
@@ -35,17 +33,16 @@
import com.android.internal.view.IInputMethodManager;
import com.android.internal.view.WindowManagerPolicyThread;
import com.android.server.AttributeCache;
+import com.android.server.DisplayThread;
import com.android.server.EventLogTags;
+import com.android.server.LocalServices;
import com.android.server.UiThread;
import com.android.server.Watchdog;
import com.android.server.am.BatteryStatsService;
-import com.android.server.display.DisplayManagerService;
import com.android.server.input.InputManagerService;
-import com.android.server.power.PowerManagerService;
import com.android.server.power.ShutdownThread;
import android.Manifest;
-import android.app.ActivityManager.StackBoxInfo;
import android.app.ActivityManagerNative;
import android.app.IActivityManager;
import android.app.StatusBarManager;
@@ -69,6 +66,7 @@
import android.graphics.RectF;
import android.graphics.Region;
import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManagerInternal;
import android.os.Binder;
import android.os.Bundle;
import android.os.Debug;
@@ -80,6 +78,7 @@
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.PowerManager;
+import android.os.PowerManagerInternal;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -117,6 +116,7 @@
import android.view.KeyEvent;
import android.view.MagnificationSpec;
import android.view.MotionEvent;
+import android.view.WindowManagerInternal;
import android.view.Surface.OutOfResourcesException;
import android.view.Surface;
import android.view.SurfaceControl;
@@ -156,7 +156,7 @@
/** {@hide} */
public class WindowManagerService extends IWindowManager.Stub
implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs,
- DisplayManagerService.WindowManagerFuncs, DisplayManager.DisplayListener {
+ DisplayManager.DisplayListener {
static final String TAG = "WindowManager";
static final boolean DEBUG = false;
static final boolean DEBUG_ADD_REMOVE = false;
@@ -293,8 +293,6 @@
final private KeyguardDisableHandler mKeyguardDisableHandler;
- private final boolean mHeadless;
-
final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -534,14 +532,15 @@
AppWindowToken mFocusedApp = null;
- PowerManagerService mPowerManager;
+ PowerManager mPowerManager;
+ PowerManagerInternal mPowerManagerInternal;
float mWindowAnimationScale = 1.0f;
float mTransitionAnimationScale = 1.0f;
float mAnimatorDurationScale = 1.0f;
final InputManagerService mInputManager;
- final DisplayManagerService mDisplayManagerService;
+ final DisplayManagerInternal mDisplayManagerInternal;
final DisplayManager mDisplayManager;
// Who is holding the screen on.
@@ -694,23 +693,22 @@
final boolean mOnlyCore;
public static WindowManagerService main(final Context context,
- final PowerManagerService pm, final DisplayManagerService dm,
- final InputManagerService im, final Handler wmHandler,
+ final InputManagerService im,
final boolean haveInputMethods, final boolean showBootMsgs,
final boolean onlyCore) {
final WindowManagerService[] holder = new WindowManagerService[1];
- wmHandler.runWithScissors(new Runnable() {
+ DisplayThread.getHandler().runWithScissors(new Runnable() {
@Override
public void run() {
- holder[0] = new WindowManagerService(context, pm, dm, im,
+ holder[0] = new WindowManagerService(context, im,
haveInputMethods, showBootMsgs, onlyCore);
}
}, 0);
return holder[0];
}
- private void initPolicy(Handler uiHandler) {
- uiHandler.runWithScissors(new Runnable() {
+ private void initPolicy() {
+ UiThread.getHandler().runWithScissors(new Runnable() {
@Override
public void run() {
WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
@@ -723,8 +721,7 @@
}, 0);
}
- private WindowManagerService(Context context, PowerManagerService pm,
- DisplayManagerService displayManager, InputManagerService inputManager,
+ private WindowManagerService(Context context, InputManagerService inputManager,
boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) {
mContext = context;
mHaveInputMethods = haveInputMethods;
@@ -733,8 +730,7 @@
mLimitedAlphaCompositing = context.getResources().getBoolean(
com.android.internal.R.bool.config_sf_limitedAlpha);
mInputManager = inputManager; // Must be before createDisplayContentLocked.
- mDisplayManagerService = displayManager;
- mHeadless = displayManager.isHeadless();
+ mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
mDisplaySettings = new DisplaySettings(context);
mDisplaySettings.readSettingsLocked();
@@ -750,10 +746,11 @@
mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy);
- mPowerManager = pm;
- mPowerManager.setPolicy(mPolicy);
- PowerManager pmc = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
- mScreenFrozenLock = pmc.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN");
+ mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+ mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
+ mPowerManagerInternal.setPolicy(mPolicy); // TODO: register as local service instead
+ mScreenFrozenLock = mPowerManager.newWakeLock(
+ PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN");
mScreenFrozenLock.setReferenceCounted(false);
mAppTransition = new AppTransition(context, mH);
@@ -783,13 +780,13 @@
filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
mContext.registerReceiver(mBroadcastReceiver, filter);
- mHoldingScreenWakeLock = pmc.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK
- | PowerManager.ON_AFTER_RELEASE, TAG);
+ mHoldingScreenWakeLock = mPowerManager.newWakeLock(
+ PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG);
mHoldingScreenWakeLock.setReferenceCounted(false);
mAnimator = new WindowAnimator(this);
- initPolicy(UiThread.getHandler());
+ initPolicy();
// Add ourself to the Watchdog monitors.
Watchdog.getInstance().addMonitor(this);
@@ -802,6 +799,8 @@
} finally {
SurfaceControl.closeTransaction();
}
+
+ LocalServices.addService(WindowManagerInternal.class, new LocalService());
}
public InputMonitor getInputMonitor() {
@@ -3626,7 +3625,7 @@
if (freezeThisOneIfNeeded != null) {
AppWindowToken atoken = findAppWindowToken(freezeThisOneIfNeeded);
if (atoken != null) {
- startAppFreezingScreenLocked(atoken, ActivityInfo.CONFIG_ORIENTATION);
+ startAppFreezingScreenLocked(atoken);
}
}
config = computeNewConfigurationLocked();
@@ -3778,10 +3777,8 @@
if (stack == null) {
mFocusedStackFrame.setVisibility(false);
} else {
- final StackBox box = stack.mStackBox;
- final Rect bounds = box.mBounds;
- final boolean multipleStacks = box.mParent != null;
- mFocusedStackFrame.setBounds(bounds);
+ mFocusedStackFrame.setBounds(stack);
+ final boolean multipleStacks = !stack.isFullscreen();
mFocusedStackFrame.setVisibility(multipleStacks);
}
} finally {
@@ -4401,8 +4398,7 @@
}
}
- public void startAppFreezingScreenLocked(AppWindowToken wtoken,
- int configChanges) {
+ private void startAppFreezingScreenLocked(AppWindowToken wtoken) {
if (DEBUG_ORIENTATION) {
RuntimeException e = null;
if (!HIDE_STACK_CRAWLS) {
@@ -4451,7 +4447,7 @@
return;
}
final long origId = Binder.clearCallingIdentity();
- startAppFreezingScreenLocked(wtoken, configChanges);
+ startAppFreezingScreenLocked(wtoken);
Binder.restoreCallingIdentity(origId);
}
}
@@ -4788,10 +4784,14 @@
}
final TaskStack stack = task.mStack;
final DisplayContent displayContent = task.getDisplayContent();
- final boolean isHomeStackTask = stack.isHomeStack();
- if (isHomeStackTask != displayContent.homeOnTop()) {
- // First move the stack itself.
- displayContent.moveHomeStackBox(isHomeStackTask);
+ displayContent.moveStack(stack, true);
+ if (displayContent.isDefaultDisplay) {
+ final TaskStack homeStack = displayContent.getHomeStack();
+ if (homeStack != stack) {
+ // When a non-home stack moves to the top, the home stack moves to the
+ // bottom.
+ displayContent.moveStack(homeStack, false);
+ }
}
stack.moveTaskToTop(task);
}
@@ -4820,56 +4820,26 @@
}
/**
- * Create a new TaskStack and place it next to an existing stack.
+ * Create a new TaskStack and place it on a DisplayContent.
* @param stackId The unique identifier of the new stack.
- * @param relativeStackBoxId The existing stack that this stack goes before or after.
- * @param position One of:
- * {@link StackBox#TASK_STACK_GOES_BEFORE}
- * {@link StackBox#TASK_STACK_GOES_AFTER}
- * {@link StackBox#TASK_STACK_GOES_ABOVE}
- * {@link StackBox#TASK_STACK_GOES_BELOW}
- * {@link StackBox#TASK_STACK_GOES_UNDER}
- * {@link StackBox#TASK_STACK_GOES_OVER}
- * @param weight Relative weight for determining how big to make the new TaskStack.
+ * @param displayId The unique identifier of the DisplayContent.
*/
- public void createStack(int stackId, int relativeStackBoxId, int position, float weight) {
- synchronized (mWindowMap) {
- if (position <= StackBox.TASK_STACK_GOES_BELOW &&
- (weight < STACK_WEIGHT_MIN || weight > STACK_WEIGHT_MAX)) {
- throw new IllegalArgumentException(
- "createStack: weight must be between " + STACK_WEIGHT_MIN + " and " +
- STACK_WEIGHT_MAX + ", weight=" + weight);
- }
- final int numDisplays = mDisplayContents.size();
- for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
- final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
- TaskStack stack = displayContent.createStack(stackId, relativeStackBoxId, position,
- weight);
- if (stack != null) {
+ public void createStack(int stackId, int displayId) {
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ synchronized (mWindowMap) {
+ final DisplayContent displayContent = mDisplayContents.get(displayId);
+ if (displayContent != null) {
+ TaskStack stack = displayContent.createStack(stackId);
mStackIdToStack.put(stackId, stack);
performLayoutAndPlaceSurfacesLocked();
- return;
}
}
- Slog.e(TAG, "createStack: Unable to find relativeStackBoxId=" + relativeStackBoxId);
+ } finally {
+ Binder.restoreCallingIdentity(origId);
}
}
- public int removeStack(int stackId) {
- synchronized (mWindowMap) {
- final TaskStack stack = mStackIdToStack.get(stackId);
- if (stack != null) {
- mStackIdToStack.delete(stackId);
- int nextStackId = stack.remove();
- stack.getDisplayContent().layoutNeeded = true;
- requestTraversalLocked();
- return nextStackId;
- }
- if (DEBUG_STACK) Slog.i(TAG, "removeStack: could not find stackId=" + stackId);
- }
- return HOME_STACK_ID;
- }
-
public void removeTask(int taskId) {
synchronized (mWindowMap) {
Task task = mTaskIdToTask.get(taskId);
@@ -4880,7 +4850,6 @@
final TaskStack stack = task.mStack;
EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, taskId, "removeTask");
stack.removeTask(task);
- stack.getDisplayContent().layoutNeeded = true;
}
}
@@ -4898,40 +4867,27 @@
}
}
- public void resizeStackBox(int stackBoxId, float weight) {
- if (weight < STACK_WEIGHT_MIN || weight > STACK_WEIGHT_MAX) {
- throw new IllegalArgumentException(
- "resizeStack: weight must be between " + STACK_WEIGHT_MIN + " and " +
- STACK_WEIGHT_MAX + ", weight=" + weight);
- }
+ public void resizeStack(int stackId, Rect bounds) {
synchronized (mWindowMap) {
- final int numDisplays = mDisplayContents.size();
- for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
- if (mDisplayContents.valueAt(displayNdx).resizeStack(stackBoxId, weight)) {
- performLayoutAndPlaceSurfacesLocked();
- return;
- }
+ final TaskStack stack = mStackIdToStack.get(stackId);
+ if (stack == null) {
+ throw new IllegalArgumentException("resizeStack: stackId " + stackId
+ + " not found.");
}
- }
- throw new IllegalArgumentException("resizeStack: stackBoxId " + stackBoxId
- + " not found.");
- }
-
- public ArrayList<StackBoxInfo> getStackBoxInfos() {
- synchronized(mWindowMap) {
- return getDefaultDisplayContentLocked().getStackBoxInfos();
+ if (stack.setBounds(bounds)) {
+ stack.getDisplayContent().layoutNeeded = true;
+ performLayoutAndPlaceSurfacesLocked();
+ }
}
}
- public Rect getStackBounds(int stackId) {
- final int numDisplays = mDisplayContents.size();
- for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
- Rect bounds = mDisplayContents.valueAt(displayNdx).getStackBounds(stackId);
- if (bounds != null) {
- return bounds;
- }
+ public void getStackBounds(int stackId, Rect bounds) {
+ final TaskStack stack = mStackIdToStack.get(stackId);
+ if (stack != null) {
+ stack.getBounds(bounds);
+ return;
}
- return null;
+ bounds.setEmpty();
}
// -------------------------------------------------------------
@@ -5259,7 +5215,7 @@
public void performBootTimeout() {
synchronized(mWindowMap) {
- if (mDisplayEnabled || mHeadless) {
+ if (mDisplayEnabled) {
return;
}
Slog.w(TAG, "***** BOOT TIMEOUT: forcing display enabled");
@@ -5443,7 +5399,6 @@
// only allow disables from pids which have count on, etc.
@Override
public void showStrictModeViolation(boolean on) {
- if (mHeadless) return;
int pid = Binder.getCallingPid();
mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, pid));
}
@@ -5589,7 +5544,7 @@
continue;
}
appWin = ws;
- stackBounds.set(ws.getStackBounds());
+ ws.getStackBounds(stackBounds);
}
}
@@ -5964,7 +5919,7 @@
}
}
- mDisplayManagerService.performTraversalInTransactionFromWindowManager();
+ mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
} finally {
if (!inTransaction) {
SurfaceControl.closeTransaction();
@@ -6658,7 +6613,7 @@
displayInfo.getLogicalMetrics(mRealDisplayMetrics,
CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
displayInfo.getAppMetrics(mDisplayMetrics);
- mDisplayManagerService.setDisplayInfoOverrideFromWindowManager(
+ mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
displayContent.getDisplayId(), displayInfo);
}
if (false) {
@@ -6991,7 +6946,7 @@
synchronized(displayContent.mDisplaySizeLock) {
// Bootstrap the default logical display from the display manager.
final DisplayInfo displayInfo = displayContent.getDisplayInfo();
- DisplayInfo newDisplayInfo = mDisplayManagerService.getDisplayInfo(displayId);
+ DisplayInfo newDisplayInfo = mDisplayManagerInternal.getDisplayInfo(displayId);
if (newDisplayInfo != null) {
displayInfo.copyFrom(newDisplayInfo);
}
@@ -7476,9 +7431,7 @@
}
case DO_DISPLAY_ADDED:
- synchronized (mWindowMap) {
- handleDisplayAddedLocked(msg.arg1);
- }
+ handleDisplayAdded(msg.arg1);
break;
case DO_DISPLAY_REMOVED:
@@ -8218,7 +8171,7 @@
}
mPolicy.getContentRectLw(mTmpContentRect);
- displayContent.setStackBoxSize(mTmpContentRect);
+ displayContent.resize(mTmpContentRect);
int seq = mLayoutSeq+1;
if (seq < 0) seq = 0;
@@ -8362,8 +8315,7 @@
// it frozen/off until this window draws at its new
// orientation.
if (!okToDisplay()) {
- if (DEBUG_ORIENTATION) Slog.v(TAG,
- "Changing surface while display frozen: " + w);
+ if (DEBUG_ORIENTATION) Slog.v(TAG, "Changing surface while display frozen: " + w);
w.mOrientationChanging = true;
w.mLastFreezeDuration = 0;
mInnerFields.mOrientationChangeComplete = false;
@@ -8813,7 +8765,8 @@
if (canBeSeen) {
// This function assumes that the contents of the default display are
// processed first before secondary displays.
- if (w.mDisplayContent.isDefaultDisplay) {
+ final DisplayContent displayContent = w.mDisplayContent;
+ if (displayContent.isDefaultDisplay) {
// While a dream or keyguard is showing, obscure ordinary application
// content on secondary displays (by forcibly enabling mirroring unless
// there is other content we want to show) but still allow opaque
@@ -9017,6 +8970,10 @@
final int N = windows.size();
for (i=N-1; i>=0; i--) {
WindowState w = windows.get(i);
+ final TaskStack stack = w.getStack();
+ if (stack == null) {
+ continue;
+ }
final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured;
@@ -9026,7 +8983,7 @@
handleNotObscuredLocked(w, currentTime, innerDw, innerDh);
}
- if (!w.getStack().testDimmingTag()) {
+ if (!stack.testDimmingTag()) {
handleFlagDimBehind(w, innerDw, innerDh);
}
@@ -9151,7 +9108,7 @@
updateResizingWindows(w);
}
- mDisplayManagerService.setDisplayHasContent(displayId,
+ mDisplayManagerInternal.setDisplayHasContent(displayId,
mInnerFields.mDisplayHasContent,
true /* inTraversal, must call performTraversalInTrans... below */);
@@ -9168,7 +9125,7 @@
// Give the display manager a chance to adjust properties
// like display rotation if it needs to.
- mDisplayManagerService.performTraversalInTransactionFromWindowManager();
+ mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
} catch (RuntimeException e) {
Log.wtf(TAG, "Unhandled exception in Window Manager", e);
@@ -9392,18 +9349,18 @@
setHoldScreenLocked(mInnerFields.mHoldScreen);
if (!mDisplayFrozen) {
if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) {
- mPowerManager.setScreenBrightnessOverrideFromWindowManager(-1);
+ mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(-1);
} else {
- mPowerManager.setScreenBrightnessOverrideFromWindowManager(
+ mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(
toBrightnessOverride(mInnerFields.mScreenBrightness));
}
if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) {
- mPowerManager.setButtonBrightnessOverrideFromWindowManager(-1);
+ mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(-1);
} else {
- mPowerManager.setButtonBrightnessOverrideFromWindowManager(
+ mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(
toBrightnessOverride(mInnerFields.mButtonBrightness));
}
- mPowerManager.setUserActivityTimeoutOverrideFromWindowManager(
+ mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager(
mInnerFields.mUserActivityTimeout);
}
@@ -9537,8 +9494,7 @@
}
}
- @Override
- public void requestTraversal() {
+ void requestTraversal() {
synchronized (mWindowMap) {
requestTraversalLocked();
}
@@ -10735,7 +10691,7 @@
displayInfo.overscanTop = rect.top;
displayInfo.overscanRight = rect.right;
displayInfo.overscanBottom = rect.bottom;
- mDisplayManagerService.setDisplayInfoOverrideFromWindowManager(
+ mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
displayId, displayInfo);
}
configureDisplayPolicyLocked(displayContent);
@@ -10810,11 +10766,13 @@
mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0));
}
- private void handleDisplayAddedLocked(int displayId) {
- final Display display = mDisplayManager.getDisplay(displayId);
- if (display != null) {
- createDisplayContentLocked(display);
- displayReady(displayId);
+ public void handleDisplayAdded(int displayId) {
+ synchronized (mWindowMap) {
+ final Display display = mDisplayManager.getDisplay(displayId);
+ if (display != null) {
+ createDisplayContentLocked(display);
+ displayReady(displayId);
+ }
}
}
@@ -10856,4 +10814,11 @@
public Object getWindowManagerLock() {
return mWindowMap;
}
+
+ private final class LocalService extends WindowManagerInternal {
+ @Override
+ public void requestTraversalFromDisplayManager() {
+ requestTraversal();
+ }
+ }
}
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
similarity index 98%
rename from services/java/com/android/server/wm/WindowState.java
rename to services/core/java/com/android/server/wm/WindowState.java
index 4d53cea..77a36b8 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -463,8 +463,8 @@
mHaveFrame = true;
TaskStack stack = mAppToken != null ? getStack() : null;
- if (stack != null && stack.hasSibling()) {
- mContainingFrame.set(getStackBounds(stack));
+ if (stack != null && !stack.isFullscreen()) {
+ getStackBounds(stack, mContainingFrame);
if (mUnderStatusBar) {
mContainingFrame.top = pf.top;
}
@@ -717,21 +717,27 @@
if (wtoken != null) {
Task task = mService.mTaskIdToTask.get(wtoken.groupId);
if (task != null) {
- return task.mStack;
+ if (task.mStack != null) {
+ return task.mStack;
+ }
+ Slog.e(TAG, "getStack: mStack null for task=" + task);
+ } else {
+ Slog.e(TAG, "getStack: couldn't find taskId=" + wtoken.groupId);
}
}
return mDisplayContent.getHomeStack();
}
- Rect getStackBounds() {
- return getStackBounds(getStack());
+ void getStackBounds(Rect bounds) {
+ getStackBounds(getStack(), bounds);
}
- private Rect getStackBounds(TaskStack stack) {
+ private void getStackBounds(TaskStack stack, Rect bounds) {
if (stack != null) {
- return stack.mStackBox.mBounds;
+ stack.getBounds(bounds);
+ return;
}
- return mFrame;
+ bounds.set(mFrame);
}
public long getInputDispatchingTimeoutNanos() {
diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
similarity index 100%
rename from services/java/com/android/server/wm/WindowStateAnimator.java
rename to services/core/java/com/android/server/wm/WindowStateAnimator.java
diff --git a/services/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
similarity index 100%
rename from services/java/com/android/server/wm/WindowToken.java
rename to services/core/java/com/android/server/wm/WindowToken.java
diff --git a/services/core/java/service.mk b/services/core/java/service.mk
new file mode 100644
index 0000000..4cb411b
--- /dev/null
+++ b/services/core/java/service.mk
@@ -0,0 +1,6 @@
+SUB_DIR := core/java
+
+LOCAL_SRC_FILES += \
+ $(call all-java-files-under,$(SUB_DIR)) \
+ $(SUB_DIR)/com/android/server/EventLogTags.logtags \
+ $(SUB_DIR)/com/android/server/am/EventLogTags.logtags
diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk
new file mode 100644
index 0000000..1a3ce63
--- /dev/null
+++ b/services/core/jni/Android.mk
@@ -0,0 +1,56 @@
+# This file is included by the top level services directory to collect source
+# files
+LOCAL_REL_DIR := core/jni
+
+LOCAL_SRC_FILES += \
+ $(LOCAL_REL_DIR)/com_android_server_AlarmManagerService.cpp \
+ $(LOCAL_REL_DIR)/com_android_server_AssetAtlasService.cpp \
+ $(LOCAL_REL_DIR)/com_android_server_ConsumerIrService.cpp \
+ $(LOCAL_REL_DIR)/com_android_server_input_InputApplicationHandle.cpp \
+ $(LOCAL_REL_DIR)/com_android_server_input_InputManagerService.cpp \
+ $(LOCAL_REL_DIR)/com_android_server_input_InputWindowHandle.cpp \
+ $(LOCAL_REL_DIR)/com_android_server_lights_LightsService.cpp \
+ $(LOCAL_REL_DIR)/com_android_server_power_PowerManagerService.cpp \
+ $(LOCAL_REL_DIR)/com_android_server_SerialService.cpp \
+ $(LOCAL_REL_DIR)/com_android_server_SystemServer.cpp \
+ $(LOCAL_REL_DIR)/com_android_server_UsbDeviceManager.cpp \
+ $(LOCAL_REL_DIR)/com_android_server_UsbHostManager.cpp \
+ $(LOCAL_REL_DIR)/com_android_server_VibratorService.cpp \
+ $(LOCAL_REL_DIR)/com_android_server_location_GpsLocationProvider.cpp \
+ $(LOCAL_REL_DIR)/com_android_server_location_FlpHardwareProvider.cpp \
+ $(LOCAL_REL_DIR)/com_android_server_connectivity_Vpn.cpp \
+ $(LOCAL_REL_DIR)/onload.cpp
+
+LOCAL_C_INCLUDES += \
+ $(JNI_H_INCLUDE) \
+ frameworks/base/services \
+ frameworks/base/libs \
+ frameworks/base/core/jni \
+ frameworks/native/services \
+ external/skia/include/core \
+ libcore/include \
+ libcore/include/libsuspend \
+ $(call include-path-for, libhardware)/hardware \
+ $(call include-path-for, libhardware_legacy)/hardware_legacy \
+
+LOCAL_SHARED_LIBRARIES += \
+ libandroid_runtime \
+ libandroidfw \
+ libbinder \
+ libcutils \
+ liblog \
+ libhardware \
+ libhardware_legacy \
+ libnativehelper \
+ libutils \
+ libui \
+ libinput \
+ libinputservice \
+ libsensorservice \
+ libskia \
+ libgui \
+ libusbhost \
+ libsuspend \
+ libEGL \
+ libGLESv2
+
diff --git a/services/jni/com_android_server_AlarmManagerService.cpp b/services/core/jni/com_android_server_AlarmManagerService.cpp
similarity index 100%
rename from services/jni/com_android_server_AlarmManagerService.cpp
rename to services/core/jni/com_android_server_AlarmManagerService.cpp
diff --git a/services/jni/com_android_server_AssetAtlasService.cpp b/services/core/jni/com_android_server_AssetAtlasService.cpp
similarity index 100%
rename from services/jni/com_android_server_AssetAtlasService.cpp
rename to services/core/jni/com_android_server_AssetAtlasService.cpp
diff --git a/services/jni/com_android_server_ConsumerIrService.cpp b/services/core/jni/com_android_server_ConsumerIrService.cpp
similarity index 100%
rename from services/jni/com_android_server_ConsumerIrService.cpp
rename to services/core/jni/com_android_server_ConsumerIrService.cpp
diff --git a/services/jni/com_android_server_SerialService.cpp b/services/core/jni/com_android_server_SerialService.cpp
similarity index 100%
rename from services/jni/com_android_server_SerialService.cpp
rename to services/core/jni/com_android_server_SerialService.cpp
diff --git a/services/jni/com_android_server_SystemServer.cpp b/services/core/jni/com_android_server_SystemServer.cpp
similarity index 100%
rename from services/jni/com_android_server_SystemServer.cpp
rename to services/core/jni/com_android_server_SystemServer.cpp
diff --git a/services/jni/com_android_server_UsbDeviceManager.cpp b/services/core/jni/com_android_server_UsbDeviceManager.cpp
similarity index 100%
rename from services/jni/com_android_server_UsbDeviceManager.cpp
rename to services/core/jni/com_android_server_UsbDeviceManager.cpp
diff --git a/services/jni/com_android_server_UsbHostManager.cpp b/services/core/jni/com_android_server_UsbHostManager.cpp
similarity index 100%
rename from services/jni/com_android_server_UsbHostManager.cpp
rename to services/core/jni/com_android_server_UsbHostManager.cpp
diff --git a/services/jni/com_android_server_VibratorService.cpp b/services/core/jni/com_android_server_VibratorService.cpp
similarity index 100%
rename from services/jni/com_android_server_VibratorService.cpp
rename to services/core/jni/com_android_server_VibratorService.cpp
diff --git a/services/jni/com_android_server_connectivity_Vpn.cpp b/services/core/jni/com_android_server_connectivity_Vpn.cpp
similarity index 100%
rename from services/jni/com_android_server_connectivity_Vpn.cpp
rename to services/core/jni/com_android_server_connectivity_Vpn.cpp
diff --git a/services/jni/com_android_server_input_InputApplicationHandle.cpp b/services/core/jni/com_android_server_input_InputApplicationHandle.cpp
similarity index 100%
rename from services/jni/com_android_server_input_InputApplicationHandle.cpp
rename to services/core/jni/com_android_server_input_InputApplicationHandle.cpp
diff --git a/services/jni/com_android_server_input_InputApplicationHandle.h b/services/core/jni/com_android_server_input_InputApplicationHandle.h
similarity index 100%
rename from services/jni/com_android_server_input_InputApplicationHandle.h
rename to services/core/jni/com_android_server_input_InputApplicationHandle.h
diff --git a/services/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
similarity index 100%
rename from services/jni/com_android_server_input_InputManagerService.cpp
rename to services/core/jni/com_android_server_input_InputManagerService.cpp
diff --git a/services/jni/com_android_server_input_InputWindowHandle.cpp b/services/core/jni/com_android_server_input_InputWindowHandle.cpp
similarity index 100%
rename from services/jni/com_android_server_input_InputWindowHandle.cpp
rename to services/core/jni/com_android_server_input_InputWindowHandle.cpp
diff --git a/services/jni/com_android_server_input_InputWindowHandle.h b/services/core/jni/com_android_server_input_InputWindowHandle.h
similarity index 100%
rename from services/jni/com_android_server_input_InputWindowHandle.h
rename to services/core/jni/com_android_server_input_InputWindowHandle.h
diff --git a/services/jni/com_android_server_LightsService.cpp b/services/core/jni/com_android_server_lights_LightsService.cpp
similarity index 97%
rename from services/jni/com_android_server_LightsService.cpp
rename to services/core/jni/com_android_server_lights_LightsService.cpp
index 69793f7..d51e044 100644
--- a/services/jni/com_android_server_LightsService.cpp
+++ b/services/core/jni/com_android_server_lights_LightsService.cpp
@@ -134,7 +134,7 @@
int register_android_server_LightsService(JNIEnv *env)
{
- return jniRegisterNativeMethods(env, "com/android/server/LightsService",
+ return jniRegisterNativeMethods(env, "com/android/server/lights/LightsService",
method_table, NELEM(method_table));
}
diff --git a/services/jni/com_android_server_location_FlpHardwareProvider.cpp b/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp
similarity index 100%
rename from services/jni/com_android_server_location_FlpHardwareProvider.cpp
rename to services/core/jni/com_android_server_location_FlpHardwareProvider.cpp
diff --git a/services/jni/com_android_server_location_GpsLocationProvider.cpp b/services/core/jni/com_android_server_location_GpsLocationProvider.cpp
similarity index 100%
rename from services/jni/com_android_server_location_GpsLocationProvider.cpp
rename to services/core/jni/com_android_server_location_GpsLocationProvider.cpp
diff --git a/services/jni/com_android_server_power_PowerManagerService.cpp b/services/core/jni/com_android_server_power_PowerManagerService.cpp
similarity index 100%
rename from services/jni/com_android_server_power_PowerManagerService.cpp
rename to services/core/jni/com_android_server_power_PowerManagerService.cpp
diff --git a/services/jni/com_android_server_power_PowerManagerService.h b/services/core/jni/com_android_server_power_PowerManagerService.h
similarity index 100%
rename from services/jni/com_android_server_power_PowerManagerService.h
rename to services/core/jni/com_android_server_power_PowerManagerService.h
diff --git a/services/jni/onload.cpp b/services/core/jni/onload.cpp
similarity index 100%
rename from services/jni/onload.cpp
rename to services/core/jni/onload.cpp
diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
similarity index 89%
rename from services/java/com/android/server/DevicePolicyManagerService.java
rename to services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 2bb99d6..af36246 100644
--- a/services/java/com/android/server/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server;
+package com.android.server.devicepolicy;
import static android.Manifest.permission.MANAGE_CA_CERTIFICATES;
@@ -117,7 +117,7 @@
*/
public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
- private static final String TAG = "DevicePolicyManagerService";
+ private static final String LOG_TAG = "DevicePolicyManagerService";
private static final String DEVICE_POLICIES_XML = "device_policies.xml";
@@ -186,7 +186,7 @@
getSendingUserId());
if (Intent.ACTION_BOOT_COMPLETED.equals(action)
|| ACTION_EXPIRED_PASSWORD_NOTIFICATION.equals(action)) {
- if (DBG) Slog.v(TAG, "Sending password expiration notifications for action "
+ if (DBG) Slog.v(LOG_TAG, "Sending password expiration notifications for action "
+ action + " for user " + userHandle);
mHandler.post(new Runnable() {
public void run() {
@@ -218,6 +218,28 @@
};
static class ActiveAdmin {
+ private static final String TAG_DISABLE_KEYGUARD_FEATURES = "disable-keyguard-features";
+ private static final String TAG_DISABLE_CAMERA = "disable-camera";
+ private static final String TAG_ENCRYPTION_REQUESTED = "encryption-requested";
+ private static final String TAG_PASSWORD_EXPIRATION_DATE = "password-expiration-date";
+ private static final String TAG_PASSWORD_EXPIRATION_TIMEOUT = "password-expiration-timeout";
+ private static final String TAG_GLOBAL_PROXY_EXCLUSION_LIST = "global-proxy-exclusion-list";
+ private static final String TAG_GLOBAL_PROXY_SPEC = "global-proxy-spec";
+ private static final String TAG_SPECIFIES_GLOBAL_PROXY = "specifies-global-proxy";
+ private static final String TAG_MAX_FAILED_PASSWORD_WIPE = "max-failed-password-wipe";
+ private static final String TAG_MAX_TIME_TO_UNLOCK = "max-time-to-unlock";
+ private static final String TAG_MIN_PASSWORD_NONLETTER = "min-password-nonletter";
+ private static final String TAG_MIN_PASSWORD_SYMBOLS = "min-password-symbols";
+ private static final String TAG_MIN_PASSWORD_NUMERIC = "min-password-numeric";
+ private static final String TAG_MIN_PASSWORD_LETTERS = "min-password-letters";
+ private static final String TAG_MIN_PASSWORD_LOWERCASE = "min-password-lowercase";
+ private static final String TAG_MIN_PASSWORD_UPPERCASE = "min-password-uppercase";
+ private static final String TAG_PASSWORD_HISTORY_LENGTH = "password-history-length";
+ private static final String TAG_MIN_PASSWORD_LENGTH = "min-password-length";
+ private static final String ATTR_VALUE = "value";
+ private static final String TAG_PASSWORD_QUALITY = "password-quality";
+ private static final String TAG_POLICIES = "policies";
+
final DeviceAdminInfo info;
int passwordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
@@ -281,103 +303,103 @@
void writeToXml(XmlSerializer out)
throws IllegalArgumentException, IllegalStateException, IOException {
- out.startTag(null, "policies");
+ out.startTag(null, TAG_POLICIES);
info.writePoliciesToXml(out);
- out.endTag(null, "policies");
+ out.endTag(null, TAG_POLICIES);
if (passwordQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
- out.startTag(null, "password-quality");
- out.attribute(null, "value", Integer.toString(passwordQuality));
- out.endTag(null, "password-quality");
+ out.startTag(null, TAG_PASSWORD_QUALITY);
+ out.attribute(null, ATTR_VALUE, Integer.toString(passwordQuality));
+ out.endTag(null, TAG_PASSWORD_QUALITY);
if (minimumPasswordLength != DEF_MINIMUM_PASSWORD_LENGTH) {
- out.startTag(null, "min-password-length");
- out.attribute(null, "value", Integer.toString(minimumPasswordLength));
- out.endTag(null, "min-password-length");
+ out.startTag(null, TAG_MIN_PASSWORD_LENGTH);
+ out.attribute(null, ATTR_VALUE, Integer.toString(minimumPasswordLength));
+ out.endTag(null, TAG_MIN_PASSWORD_LENGTH);
}
if(passwordHistoryLength != DEF_PASSWORD_HISTORY_LENGTH) {
- out.startTag(null, "password-history-length");
- out.attribute(null, "value", Integer.toString(passwordHistoryLength));
- out.endTag(null, "password-history-length");
+ out.startTag(null, TAG_PASSWORD_HISTORY_LENGTH);
+ out.attribute(null, ATTR_VALUE, Integer.toString(passwordHistoryLength));
+ out.endTag(null, TAG_PASSWORD_HISTORY_LENGTH);
}
if (minimumPasswordUpperCase != DEF_MINIMUM_PASSWORD_UPPER_CASE) {
- out.startTag(null, "min-password-uppercase");
- out.attribute(null, "value", Integer.toString(minimumPasswordUpperCase));
- out.endTag(null, "min-password-uppercase");
+ out.startTag(null, TAG_MIN_PASSWORD_UPPERCASE);
+ out.attribute(null, ATTR_VALUE, Integer.toString(minimumPasswordUpperCase));
+ out.endTag(null, TAG_MIN_PASSWORD_UPPERCASE);
}
if (minimumPasswordLowerCase != DEF_MINIMUM_PASSWORD_LOWER_CASE) {
- out.startTag(null, "min-password-lowercase");
- out.attribute(null, "value", Integer.toString(minimumPasswordLowerCase));
- out.endTag(null, "min-password-lowercase");
+ out.startTag(null, TAG_MIN_PASSWORD_LOWERCASE);
+ out.attribute(null, ATTR_VALUE, Integer.toString(minimumPasswordLowerCase));
+ out.endTag(null, TAG_MIN_PASSWORD_LOWERCASE);
}
if (minimumPasswordLetters != DEF_MINIMUM_PASSWORD_LETTERS) {
- out.startTag(null, "min-password-letters");
- out.attribute(null, "value", Integer.toString(minimumPasswordLetters));
- out.endTag(null, "min-password-letters");
+ out.startTag(null, TAG_MIN_PASSWORD_LETTERS);
+ out.attribute(null, ATTR_VALUE, Integer.toString(minimumPasswordLetters));
+ out.endTag(null, TAG_MIN_PASSWORD_LETTERS);
}
if (minimumPasswordNumeric != DEF_MINIMUM_PASSWORD_NUMERIC) {
- out.startTag(null, "min-password-numeric");
- out.attribute(null, "value", Integer.toString(minimumPasswordNumeric));
- out.endTag(null, "min-password-numeric");
+ out.startTag(null, TAG_MIN_PASSWORD_NUMERIC);
+ out.attribute(null, ATTR_VALUE, Integer.toString(minimumPasswordNumeric));
+ out.endTag(null, TAG_MIN_PASSWORD_NUMERIC);
}
if (minimumPasswordSymbols != DEF_MINIMUM_PASSWORD_SYMBOLS) {
- out.startTag(null, "min-password-symbols");
- out.attribute(null, "value", Integer.toString(minimumPasswordSymbols));
- out.endTag(null, "min-password-symbols");
+ out.startTag(null, TAG_MIN_PASSWORD_SYMBOLS);
+ out.attribute(null, ATTR_VALUE, Integer.toString(minimumPasswordSymbols));
+ out.endTag(null, TAG_MIN_PASSWORD_SYMBOLS);
}
if (minimumPasswordNonLetter > DEF_MINIMUM_PASSWORD_NON_LETTER) {
- out.startTag(null, "min-password-nonletter");
- out.attribute(null, "value", Integer.toString(minimumPasswordNonLetter));
- out.endTag(null, "min-password-nonletter");
+ out.startTag(null, TAG_MIN_PASSWORD_NONLETTER);
+ out.attribute(null, ATTR_VALUE, Integer.toString(minimumPasswordNonLetter));
+ out.endTag(null, TAG_MIN_PASSWORD_NONLETTER);
}
}
if (maximumTimeToUnlock != DEF_MAXIMUM_TIME_TO_UNLOCK) {
- out.startTag(null, "max-time-to-unlock");
- out.attribute(null, "value", Long.toString(maximumTimeToUnlock));
- out.endTag(null, "max-time-to-unlock");
+ out.startTag(null, TAG_MAX_TIME_TO_UNLOCK);
+ out.attribute(null, ATTR_VALUE, Long.toString(maximumTimeToUnlock));
+ out.endTag(null, TAG_MAX_TIME_TO_UNLOCK);
}
if (maximumFailedPasswordsForWipe != DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE) {
- out.startTag(null, "max-failed-password-wipe");
- out.attribute(null, "value", Integer.toString(maximumFailedPasswordsForWipe));
- out.endTag(null, "max-failed-password-wipe");
+ out.startTag(null, TAG_MAX_FAILED_PASSWORD_WIPE);
+ out.attribute(null, ATTR_VALUE, Integer.toString(maximumFailedPasswordsForWipe));
+ out.endTag(null, TAG_MAX_FAILED_PASSWORD_WIPE);
}
if (specifiesGlobalProxy) {
- out.startTag(null, "specifies-global-proxy");
- out.attribute(null, "value", Boolean.toString(specifiesGlobalProxy));
- out.endTag(null, "specifies_global_proxy");
+ out.startTag(null, TAG_SPECIFIES_GLOBAL_PROXY);
+ out.attribute(null, ATTR_VALUE, Boolean.toString(specifiesGlobalProxy));
+ out.endTag(null, TAG_SPECIFIES_GLOBAL_PROXY);
if (globalProxySpec != null) {
- out.startTag(null, "global-proxy-spec");
- out.attribute(null, "value", globalProxySpec);
- out.endTag(null, "global-proxy-spec");
+ out.startTag(null, TAG_GLOBAL_PROXY_SPEC);
+ out.attribute(null, ATTR_VALUE, globalProxySpec);
+ out.endTag(null, TAG_GLOBAL_PROXY_SPEC);
}
if (globalProxyExclusionList != null) {
- out.startTag(null, "global-proxy-exclusion-list");
- out.attribute(null, "value", globalProxyExclusionList);
- out.endTag(null, "global-proxy-exclusion-list");
+ out.startTag(null, TAG_GLOBAL_PROXY_EXCLUSION_LIST);
+ out.attribute(null, ATTR_VALUE, globalProxyExclusionList);
+ out.endTag(null, TAG_GLOBAL_PROXY_EXCLUSION_LIST);
}
}
if (passwordExpirationTimeout != DEF_PASSWORD_EXPIRATION_TIMEOUT) {
- out.startTag(null, "password-expiration-timeout");
- out.attribute(null, "value", Long.toString(passwordExpirationTimeout));
- out.endTag(null, "password-expiration-timeout");
+ out.startTag(null, TAG_PASSWORD_EXPIRATION_TIMEOUT);
+ out.attribute(null, ATTR_VALUE, Long.toString(passwordExpirationTimeout));
+ out.endTag(null, TAG_PASSWORD_EXPIRATION_TIMEOUT);
}
if (passwordExpirationDate != DEF_PASSWORD_EXPIRATION_DATE) {
- out.startTag(null, "password-expiration-date");
- out.attribute(null, "value", Long.toString(passwordExpirationDate));
- out.endTag(null, "password-expiration-date");
+ out.startTag(null, TAG_PASSWORD_EXPIRATION_DATE);
+ out.attribute(null, ATTR_VALUE, Long.toString(passwordExpirationDate));
+ out.endTag(null, TAG_PASSWORD_EXPIRATION_DATE);
}
if (encryptionRequested) {
- out.startTag(null, "encryption-requested");
- out.attribute(null, "value", Boolean.toString(encryptionRequested));
- out.endTag(null, "encryption-requested");
+ out.startTag(null, TAG_ENCRYPTION_REQUESTED);
+ out.attribute(null, ATTR_VALUE, Boolean.toString(encryptionRequested));
+ out.endTag(null, TAG_ENCRYPTION_REQUESTED);
}
if (disableCamera) {
- out.startTag(null, "disable-camera");
- out.attribute(null, "value", Boolean.toString(disableCamera));
- out.endTag(null, "disable-camera");
+ out.startTag(null, TAG_DISABLE_CAMERA);
+ out.attribute(null, ATTR_VALUE, Boolean.toString(disableCamera));
+ out.endTag(null, TAG_DISABLE_CAMERA);
}
if (disabledKeyguardFeatures != DEF_KEYGUARD_FEATURES_DISABLED) {
- out.startTag(null, "disable-keyguard-features");
- out.attribute(null, "value", Integer.toString(disabledKeyguardFeatures));
- out.endTag(null, "disable-keyguard-features");
+ out.startTag(null, TAG_DISABLE_KEYGUARD_FEATURES);
+ out.attribute(null, ATTR_VALUE, Integer.toString(disabledKeyguardFeatures));
+ out.endTag(null, TAG_DISABLE_KEYGUARD_FEATURES);
}
}
@@ -391,67 +413,67 @@
continue;
}
String tag = parser.getName();
- if ("policies".equals(tag)) {
+ if (TAG_POLICIES.equals(tag)) {
info.readPoliciesFromXml(parser);
- } else if ("password-quality".equals(tag)) {
+ } else if (TAG_PASSWORD_QUALITY.equals(tag)) {
passwordQuality = Integer.parseInt(
- parser.getAttributeValue(null, "value"));
- } else if ("min-password-length".equals(tag)) {
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_MIN_PASSWORD_LENGTH.equals(tag)) {
minimumPasswordLength = Integer.parseInt(
- parser.getAttributeValue(null, "value"));
- } else if ("password-history-length".equals(tag)) {
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_PASSWORD_HISTORY_LENGTH.equals(tag)) {
passwordHistoryLength = Integer.parseInt(
- parser.getAttributeValue(null, "value"));
- } else if ("min-password-uppercase".equals(tag)) {
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_MIN_PASSWORD_UPPERCASE.equals(tag)) {
minimumPasswordUpperCase = Integer.parseInt(
- parser.getAttributeValue(null, "value"));
- } else if ("min-password-lowercase".equals(tag)) {
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_MIN_PASSWORD_LOWERCASE.equals(tag)) {
minimumPasswordLowerCase = Integer.parseInt(
- parser.getAttributeValue(null, "value"));
- } else if ("min-password-letters".equals(tag)) {
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_MIN_PASSWORD_LETTERS.equals(tag)) {
minimumPasswordLetters = Integer.parseInt(
- parser.getAttributeValue(null, "value"));
- } else if ("min-password-numeric".equals(tag)) {
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_MIN_PASSWORD_NUMERIC.equals(tag)) {
minimumPasswordNumeric = Integer.parseInt(
- parser.getAttributeValue(null, "value"));
- } else if ("min-password-symbols".equals(tag)) {
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_MIN_PASSWORD_SYMBOLS.equals(tag)) {
minimumPasswordSymbols = Integer.parseInt(
- parser.getAttributeValue(null, "value"));
- } else if ("min-password-nonletter".equals(tag)) {
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_MIN_PASSWORD_NONLETTER.equals(tag)) {
minimumPasswordNonLetter = Integer.parseInt(
- parser.getAttributeValue(null, "value"));
- } else if ("max-time-to-unlock".equals(tag)) {
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_MAX_TIME_TO_UNLOCK.equals(tag)) {
maximumTimeToUnlock = Long.parseLong(
- parser.getAttributeValue(null, "value"));
- } else if ("max-failed-password-wipe".equals(tag)) {
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_MAX_FAILED_PASSWORD_WIPE.equals(tag)) {
maximumFailedPasswordsForWipe = Integer.parseInt(
- parser.getAttributeValue(null, "value"));
- } else if ("specifies-global-proxy".equals(tag)) {
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_SPECIFIES_GLOBAL_PROXY.equals(tag)) {
specifiesGlobalProxy = Boolean.parseBoolean(
- parser.getAttributeValue(null, "value"));
- } else if ("global-proxy-spec".equals(tag)) {
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_GLOBAL_PROXY_SPEC.equals(tag)) {
globalProxySpec =
- parser.getAttributeValue(null, "value");
- } else if ("global-proxy-exclusion-list".equals(tag)) {
+ parser.getAttributeValue(null, ATTR_VALUE);
+ } else if (TAG_GLOBAL_PROXY_EXCLUSION_LIST.equals(tag)) {
globalProxyExclusionList =
- parser.getAttributeValue(null, "value");
- } else if ("password-expiration-timeout".equals(tag)) {
+ parser.getAttributeValue(null, ATTR_VALUE);
+ } else if (TAG_PASSWORD_EXPIRATION_TIMEOUT.equals(tag)) {
passwordExpirationTimeout = Long.parseLong(
- parser.getAttributeValue(null, "value"));
- } else if ("password-expiration-date".equals(tag)) {
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_PASSWORD_EXPIRATION_DATE.equals(tag)) {
passwordExpirationDate = Long.parseLong(
- parser.getAttributeValue(null, "value"));
- } else if ("encryption-requested".equals(tag)) {
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_ENCRYPTION_REQUESTED.equals(tag)) {
encryptionRequested = Boolean.parseBoolean(
- parser.getAttributeValue(null, "value"));
- } else if ("disable-camera".equals(tag)) {
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_DISABLE_CAMERA.equals(tag)) {
disableCamera = Boolean.parseBoolean(
- parser.getAttributeValue(null, "value"));
- } else if ("disable-keyguard-features".equals(tag)) {
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_DISABLE_KEYGUARD_FEATURES.equals(tag)) {
disabledKeyguardFeatures = Integer.parseInt(
- parser.getAttributeValue(null, "value"));
+ parser.getAttributeValue(null, ATTR_VALUE));
} else {
- Slog.w(TAG, "Unknown admin tag: " + tag);
+ Slog.w(LOG_TAG, "Unknown admin tag: " + tag);
}
XmlUtils.skipCurrentTag(parser);
}
@@ -513,7 +535,7 @@
private void handlePackagesChanged(int userHandle) {
boolean removed = false;
- if (DBG) Slog.d(TAG, "Handling package changes for user " + userHandle);
+ if (DBG) Slog.d(LOG_TAG, "Handling package changes for user " + userHandle);
DevicePolicyData policy = getUserData(userHandle);
IPackageManager pm = AppGlobals.getPackageManager();
for (int i = policy.mAdminList.size() - 1; i >= 0; i--) {
@@ -585,7 +607,7 @@
void removeUserData(int userHandle) {
synchronized (this) {
if (userHandle == UserHandle.USER_OWNER) {
- Slog.w(TAG, "Tried to remove device policy file for user 0! Ignoring.");
+ Slog.w(LOG_TAG, "Tried to remove device policy file for user 0! Ignoring.");
return;
}
DevicePolicyData policy = mUserData.get(userHandle);
@@ -595,7 +617,7 @@
File policyFile = new File(Environment.getUserSystemDirectory(userHandle),
DEVICE_POLICIES_XML);
policyFile.delete();
- Slog.i(TAG, "Removed device policy file " + policyFile.getAbsolutePath());
+ Slog.i(LOG_TAG, "Removed device policy file " + policyFile.getAbsolutePath());
}
}
@@ -792,10 +814,12 @@
try {
return new DeviceAdminInfo(mContext, infos.get(0));
} catch (XmlPullParserException e) {
- Slog.w(TAG, "Bad device admin requested for user=" + userHandle + ": " + adminName, e);
+ Slog.w(LOG_TAG, "Bad device admin requested for user=" + userHandle + ": " + adminName,
+ e);
return null;
} catch (IOException e) {
- Slog.w(TAG, "Bad device admin requested for user=" + userHandle + ": " + adminName, e);
+ Slog.w(LOG_TAG, "Bad device admin requested for user=" + userHandle + ": " + adminName,
+ e);
return null;
}
}
@@ -922,7 +946,7 @@
ComponentName.unflattenFromString(name), userHandle);
if (DBG && (UserHandle.getUserId(dai.getActivityInfo().applicationInfo.uid)
!= userHandle)) {
- Slog.w(TAG, "findAdmin returned an incorrect uid "
+ Slog.w(LOG_TAG, "findAdmin returned an incorrect uid "
+ dai.getActivityInfo().applicationInfo.uid + " for user "
+ userHandle);
}
@@ -933,7 +957,7 @@
policy.mAdminList.add(ap);
}
} catch (RuntimeException e) {
- Slog.w(TAG, "Failed loading admin " + name, e);
+ Slog.w(LOG_TAG, "Failed loading admin " + name, e);
}
} else if ("failed-password-attempts".equals(tag)) {
policy.mFailedPasswordAttempts = Integer.parseInt(
@@ -962,22 +986,22 @@
parser.getAttributeValue(null, "nonletter"));
XmlUtils.skipCurrentTag(parser);
} else {
- Slog.w(TAG, "Unknown tag: " + tag);
+ Slog.w(LOG_TAG, "Unknown tag: " + tag);
XmlUtils.skipCurrentTag(parser);
}
}
} catch (NullPointerException e) {
- Slog.w(TAG, "failed parsing " + file + " " + e);
+ Slog.w(LOG_TAG, "failed parsing " + file + " " + e);
} catch (NumberFormatException e) {
- Slog.w(TAG, "failed parsing " + file + " " + e);
+ Slog.w(LOG_TAG, "failed parsing " + file + " " + e);
} catch (XmlPullParserException e) {
- Slog.w(TAG, "failed parsing " + file + " " + e);
+ Slog.w(LOG_TAG, "failed parsing " + file + " " + e);
} catch (FileNotFoundException e) {
// Don't be noisy, this is normal if we haven't defined any policies.
} catch (IOException e) {
- Slog.w(TAG, "failed parsing " + file + " " + e);
+ Slog.w(LOG_TAG, "failed parsing " + file + " " + e);
} catch (IndexOutOfBoundsException e) {
- Slog.w(TAG, "failed parsing " + file + " " + e);
+ Slog.w(LOG_TAG, "failed parsing " + file + " " + e);
}
try {
if (stream != null) {
@@ -993,7 +1017,7 @@
// never normally happen.
LockPatternUtils utils = new LockPatternUtils(mContext);
if (utils.getActivePasswordQuality() < policy.mActivePasswordQuality) {
- Slog.w(TAG, "Active password quality 0x"
+ Slog.w(LOG_TAG, "Active password quality 0x"
+ Integer.toHexString(policy.mActivePasswordQuality)
+ " does not match actual quality 0x"
+ Integer.toHexString(utils.getActivePasswordQuality()));
@@ -1037,7 +1061,7 @@
}
}
if (!haveOwner) {
- Slog.w(TAG, "Previous password owner " + policy.mPasswordOwner
+ Slog.w(LOG_TAG, "Previous password owner " + policy.mPasswordOwner
+ " no longer active; disabling");
policy.mPasswordOwner = -1;
}
@@ -1057,7 +1081,7 @@
long token = Binder.clearCallingIdentity();
try {
String value = cameraDisabled ? "1" : "0";
- if (DBG) Slog.v(TAG, "Change in camera state ["
+ if (DBG) Slog.v(LOG_TAG, "Change in camera state ["
+ SYSTEM_PROP_DISABLE_CAMERA + "] = " + value);
SystemProperties.set(SYSTEM_PROP_DISABLE_CAMERA, value);
} finally {
@@ -1173,7 +1197,8 @@
synchronized (this) {
long ident = Binder.clearCallingIdentity();
try {
- if (!refreshing && getActiveAdminUncheckedLocked(adminReceiver, userHandle) != null) {
+ if (!refreshing
+ && getActiveAdminUncheckedLocked(adminReceiver, userHandle) != null) {
throw new IllegalArgumentException("Admin is already added");
}
ActiveAdmin newAdmin = new ActiveAdmin(info);
@@ -1443,7 +1468,7 @@
ap.passwordExpirationDate = expiration;
ap.passwordExpirationTimeout = timeout;
if (timeout > 0L) {
- Slog.w(TAG, "setPasswordExpiration(): password will expire on "
+ Slog.w(LOG_TAG, "setPasswordExpiration(): password will expire on "
+ DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT)
.format(new Date(expiration)));
}
@@ -1789,11 +1814,11 @@
return true;
}
return policy.mActivePasswordUpperCase >= getPasswordMinimumUpperCase(null, userHandle)
- && policy.mActivePasswordLowerCase >= getPasswordMinimumLowerCase(null, userHandle)
- && policy.mActivePasswordLetters >= getPasswordMinimumLetters(null, userHandle)
- && policy.mActivePasswordNumeric >= getPasswordMinimumNumeric(null, userHandle)
- && policy.mActivePasswordSymbols >= getPasswordMinimumSymbols(null, userHandle)
- && policy.mActivePasswordNonLetter >= getPasswordMinimumNonLetter(null, userHandle);
+ && policy.mActivePasswordLowerCase >= getPasswordMinimumLowerCase(null, userHandle)
+ && policy.mActivePasswordLetters >= getPasswordMinimumLetters(null, userHandle)
+ && policy.mActivePasswordNumeric >= getPasswordMinimumNumeric(null, userHandle)
+ && policy.mActivePasswordSymbols >= getPasswordMinimumSymbols(null, userHandle)
+ && policy.mActivePasswordNonLetter >= getPasswordMinimumNonLetter(null, userHandle);
}
}
@@ -1871,7 +1896,7 @@
int realQuality = LockPatternUtils.computePasswordQuality(password);
if (realQuality < quality
&& quality != DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) {
- Slog.w(TAG, "resetPassword: password quality 0x"
+ Slog.w(LOG_TAG, "resetPassword: password quality 0x"
+ Integer.toHexString(realQuality)
+ " does not meet required quality 0x"
+ Integer.toHexString(quality));
@@ -1881,7 +1906,7 @@
}
int length = getPasswordMinimumLength(null, userHandle);
if (password.length() < length) {
- Slog.w(TAG, "resetPassword: password length " + password.length()
+ Slog.w(LOG_TAG, "resetPassword: password length " + password.length()
+ " does not meet required length " + length);
return false;
}
@@ -1910,40 +1935,40 @@
}
int neededLetters = getPasswordMinimumLetters(null, userHandle);
if(letters < neededLetters) {
- Slog.w(TAG, "resetPassword: number of letters " + letters
+ Slog.w(LOG_TAG, "resetPassword: number of letters " + letters
+ " does not meet required number of letters " + neededLetters);
return false;
}
int neededNumbers = getPasswordMinimumNumeric(null, userHandle);
if (numbers < neededNumbers) {
- Slog.w(TAG, "resetPassword: number of numerical digits " + numbers
+ Slog.w(LOG_TAG, "resetPassword: number of numerical digits " + numbers
+ " does not meet required number of numerical digits "
+ neededNumbers);
return false;
}
int neededLowerCase = getPasswordMinimumLowerCase(null, userHandle);
if (lowercase < neededLowerCase) {
- Slog.w(TAG, "resetPassword: number of lowercase letters " + lowercase
+ Slog.w(LOG_TAG, "resetPassword: number of lowercase letters " + lowercase
+ " does not meet required number of lowercase letters "
+ neededLowerCase);
return false;
}
int neededUpperCase = getPasswordMinimumUpperCase(null, userHandle);
if (uppercase < neededUpperCase) {
- Slog.w(TAG, "resetPassword: number of uppercase letters " + uppercase
+ Slog.w(LOG_TAG, "resetPassword: number of uppercase letters " + uppercase
+ " does not meet required number of uppercase letters "
+ neededUpperCase);
return false;
}
int neededSymbols = getPasswordMinimumSymbols(null, userHandle);
if (symbols < neededSymbols) {
- Slog.w(TAG, "resetPassword: number of special symbols " + symbols
+ Slog.w(LOG_TAG, "resetPassword: number of special symbols " + symbols
+ " does not meet required number of special symbols " + neededSymbols);
return false;
}
int neededNonLetter = getPasswordMinimumNonLetter(null, userHandle);
if (nonletter < neededNonLetter) {
- Slog.w(TAG, "resetPassword: number of non-letter characters " + nonletter
+ Slog.w(LOG_TAG, "resetPassword: number of non-letter characters " + nonletter
+ " does not meet required number of non-letter characters "
+ neededNonLetter);
return false;
@@ -1954,7 +1979,7 @@
int callingUid = Binder.getCallingUid();
DevicePolicyData policy = getUserData(userHandle);
if (policy.mPasswordOwner >= 0 && policy.mPasswordOwner != callingUid) {
- Slog.w(TAG, "resetPassword: already set by another uid and not entered by user");
+ Slog.w(LOG_TAG, "resetPassword: already set by another uid and not entered by user");
return false;
}
@@ -2020,7 +2045,7 @@
try {
getIPowerManager().setMaximumScreenOffTimeoutFromDeviceAdmin((int)timeMs);
} catch (RemoteException e) {
- Slog.w(TAG, "Failure talking with power manager", e);
+ Slog.w(LOG_TAG, "Failure talking with power manager", e);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -2095,10 +2120,10 @@
X509Certificate cert = parseCert(certBuffer);
pemCert = Credentials.convertToPem(cert);
} catch (CertificateException ce) {
- Log.e(TAG, "Problem converting cert", ce);
+ Log.e(LOG_TAG, "Problem converting cert", ce);
return false;
} catch (IOException ioe) {
- Log.e(TAG, "Problem reading cert", ioe);
+ Log.e(LOG_TAG, "Problem reading cert", ioe);
return false;
}
try {
@@ -2113,7 +2138,7 @@
}
}
} catch (InterruptedException e1) {
- Log.w(TAG, "installCaCertsToKeyChain(): ", e1);
+ Log.w(LOG_TAG, "installCaCertsToKeyChain(): ", e1);
Thread.currentThread().interrupt();
}
return false;
@@ -2134,10 +2159,10 @@
X509Certificate cert = parseCert(certBuffer);
alias = certStore.getCertificateAlias(cert);
} catch (CertificateException ce) {
- Log.e(TAG, "Problem creating X509Certificate", ce);
+ Log.e(LOG_TAG, "Problem creating X509Certificate", ce);
return;
} catch (IOException ioe) {
- Log.e(TAG, "Problem reading certificate", ioe);
+ Log.e(LOG_TAG, "Problem reading certificate", ioe);
return;
}
try {
@@ -2146,13 +2171,13 @@
try {
service.deleteCaCertificate(alias);
} catch (RemoteException e) {
- Log.e(TAG, "from CaCertUninstaller: ", e);
+ Log.e(LOG_TAG, "from CaCertUninstaller: ", e);
} finally {
keyChainConnection.close();
keyChainConnection = null;
}
} catch (InterruptedException ie) {
- Log.w(TAG, "CaCertUninstaller: ", ie);
+ Log.w(LOG_TAG, "CaCertUninstaller: ", ie);
Thread.currentThread().interrupt();
}
}
@@ -2173,7 +2198,7 @@
try {
RecoverySystem.rebootWipeUserData(mContext);
} catch (IOException e) {
- Slog.w(TAG, "Failed requesting data wipe", e);
+ Slog.w(LOG_TAG, "Failed requesting data wipe", e);
}
}
}
@@ -2264,8 +2289,10 @@
if (p.mActivePasswordQuality != quality || p.mActivePasswordLength != length
|| p.mFailedPasswordAttempts != 0 || p.mActivePasswordLetters != letters
|| p.mActivePasswordUpperCase != uppercase
- || p.mActivePasswordLowerCase != lowercase || p.mActivePasswordNumeric != numbers
- || p.mActivePasswordSymbols != symbols || p.mActivePasswordNonLetter != nonletter) {
+ || p.mActivePasswordLowerCase != lowercase
+ || p.mActivePasswordNumeric != numbers
+ || p.mActivePasswordSymbols != symbols
+ || p.mActivePasswordNonLetter != nonletter) {
long ident = Binder.clearCallingIdentity();
try {
p.mActivePasswordQuality = quality;
@@ -2387,7 +2414,7 @@
// If the user is not the owner, don't set the global proxy. Fail silently.
if (UserHandle.getCallingUserId() != UserHandle.USER_OWNER) {
- Slog.w(TAG, "Only the owner is allowed to set the global proxy. User "
+ Slog.w(LOG_TAG, "Only the owner is allowed to set the global proxy. User "
+ userHandle + " is not permitted.");
return null;
}
@@ -2468,7 +2495,7 @@
ProxyProperties proxyProperties = new ProxyProperties(data[0], proxyPort, exclusionList);
if (!proxyProperties.isValid()) {
- Slog.e(TAG, "Invalid proxy properties, ignoring: " + proxyProperties.toString());
+ Slog.e(LOG_TAG, "Invalid proxy properties, ignoring: " + proxyProperties.toString());
return;
}
Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_HOST, data[0]);
@@ -2494,7 +2521,7 @@
// Only owner can set storage encryption
if (userHandle != UserHandle.USER_OWNER
|| UserHandle.getCallingUserId() != UserHandle.USER_OWNER) {
- Slog.w(TAG, "Only owner is allowed to set storage encryption. User "
+ Slog.w(LOG_TAG, "Only owner is allowed to set storage encryption. User "
+ UserHandle.getCallingUserId() + " is not permitted.");
return 0;
}
@@ -2880,7 +2907,7 @@
}
}
} catch (NameNotFoundException nnfe) {
- Slog.w(TAG, "Device Owner package " + packageName + " not installed.");
+ Slog.w(LOG_TAG, "Device Owner package " + packageName + " not installed.");
}
return false;
}
@@ -2905,9 +2932,9 @@
mOwnerName = parser.getAttributeValue(null, ATTR_NAME);
input.close();
} catch (XmlPullParserException xppe) {
- Slog.e(TAG, "Error parsing device-owner file\n" + xppe);
+ Slog.e(LOG_TAG, "Error parsing device-owner file\n" + xppe);
} catch (IOException ioe) {
- Slog.e(TAG, "IO Exception when reading device-owner file\n" + ioe);
+ Slog.e(LOG_TAG, "IO Exception when reading device-owner file\n" + ioe);
}
}
@@ -2935,7 +2962,7 @@
out.flush();
file.finishWrite(output);
} catch (IOException ioe) {
- Slog.e(TAG, "IO Exception when writing device-owner file\n" + ioe);
+ Slog.e(LOG_TAG, "IO Exception when writing device-owner file\n" + ioe);
}
}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerSystemService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerSystemService.java
new file mode 100644
index 0000000..160aa39
--- /dev/null
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerSystemService.java
@@ -0,0 +1,46 @@
+/*
+ * 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.server.devicepolicy;
+
+import android.content.Context;
+
+import com.android.server.SystemService;
+
+/**
+ * SystemService wrapper for the DevicePolicyManager implementation. Publishes
+ * Context.DEVICE_POLICY_SERVICE.
+ */
+public final class DevicePolicyManagerSystemService extends SystemService {
+ private DevicePolicyManagerService mDevicePolicyManagerImpl;
+
+ @Override
+ public void onCreate(Context context) {
+ mDevicePolicyManagerImpl = new DevicePolicyManagerService(context);
+ }
+
+ @Override
+ public void onStart() {
+ publishBinderService(Context.DEVICE_POLICY_SERVICE, mDevicePolicyManagerImpl);
+ }
+
+ @Override
+ public void onBootPhase(int phase) {
+ if (phase == PHASE_LOCK_SETTINGS_READY) {
+ mDevicePolicyManagerImpl.systemReady();
+ }
+ }
+}
\ No newline at end of file
diff --git a/services/devicepolicy/java/service.mk b/services/devicepolicy/java/service.mk
new file mode 100644
index 0000000..e64cc96
--- /dev/null
+++ b/services/devicepolicy/java/service.mk
@@ -0,0 +1,11 @@
+# Include only if the service is required
+ifneq ($(findstring devicepolicy,$(REQUIRED_SERVICES)),)
+
+SUB_DIR := devicepolicy/java
+
+LOCAL_SRC_FILES += \
+ $(call all-java-files-under,$(SUB_DIR))
+
+#DEFINED_SERVICES += com.android.server.devicepolicy.DevicePolicyManagerService
+
+endif
diff --git a/services/java/Android.mk b/services/java/Android.mk
deleted file mode 100644
index 8c3d0f0..0000000
--- a/services/java/Android.mk
+++ /dev/null
@@ -1,18 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-# the library
-# ============================================================
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
- $(call all-subdir-java-files) \
- com/android/server/EventLogTags.logtags \
- com/android/server/am/EventLogTags.logtags
-
-LOCAL_MODULE:= services
-
-LOCAL_JAVA_LIBRARIES := android.policy conscrypt telephony-common
-
-include $(BUILD_JAVA_LIBRARY)
-
-include $(BUILD_DROIDDOC)
diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java
deleted file mode 100644
index 203cca6..0000000
--- a/services/java/com/android/server/AppWidgetService.java
+++ /dev/null
@@ -1,363 +0,0 @@
-/*
- * Copyright (C) 2007 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.app.ActivityManager;
-import android.appwidget.AppWidgetProviderInfo;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.util.Slog;
-import android.util.SparseArray;
-import android.widget.RemoteViews;
-
-import com.android.internal.appwidget.IAppWidgetHost;
-import com.android.internal.appwidget.IAppWidgetService;
-import com.android.internal.os.BackgroundThread;
-import com.android.internal.util.IndentingPrintWriter;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.List;
-import java.util.Locale;
-
-
-/**
- * Redirects calls to this service to the instance of the service for the appropriate user.
- */
-class AppWidgetService extends IAppWidgetService.Stub
-{
- private static final String TAG = "AppWidgetService";
-
- Context mContext;
- Locale mLocale;
- PackageManager mPackageManager;
- boolean mSafeMode;
- private final Handler mSaveStateHandler;
-
- private final SparseArray<AppWidgetServiceImpl> mAppWidgetServices;
-
- AppWidgetService(Context context) {
- mContext = context;
-
- mSaveStateHandler = BackgroundThread.getHandler();
-
- mAppWidgetServices = new SparseArray<AppWidgetServiceImpl>(5);
- AppWidgetServiceImpl primary = new AppWidgetServiceImpl(context, 0, mSaveStateHandler);
- mAppWidgetServices.append(0, primary);
- }
-
- public void systemRunning(boolean safeMode) {
- mSafeMode = safeMode;
-
- mAppWidgetServices.get(0).systemReady(safeMode);
-
- // Register for the boot completed broadcast, so we can send the
- // ENABLE broacasts. If we try to send them now, they time out,
- // because the system isn't ready to handle them yet.
- mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
- new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null);
-
- // Register for configuration changes so we can update the names
- // of the widgets when the locale changes.
- mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
- new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED), null, null);
-
- // Register for broadcasts about package install, etc., so we can
- // update the provider list.
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_PACKAGE_ADDED);
- filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
- filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
- filter.addDataScheme("package");
- mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
- filter, null, null);
- // Register for events related to sdcard installation.
- IntentFilter sdFilter = new IntentFilter();
- sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
- sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
- mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
- sdFilter, null, null);
-
- IntentFilter userFilter = new IntentFilter();
- userFilter.addAction(Intent.ACTION_USER_REMOVED);
- userFilter.addAction(Intent.ACTION_USER_STOPPING);
- mContext.registerReceiver(new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
- onUserRemoved(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
- UserHandle.USER_NULL));
- } else if (Intent.ACTION_USER_STOPPING.equals(intent.getAction())) {
- onUserStopping(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
- UserHandle.USER_NULL));
- }
- }
- }, userFilter);
- }
-
- @Override
- public int allocateAppWidgetId(String packageName, int hostId, int userId)
- throws RemoteException {
- return getImplForUser(userId).allocateAppWidgetId(packageName, hostId);
- }
-
- @Override
- public int[] getAppWidgetIdsForHost(int hostId, int userId) throws RemoteException {
- return getImplForUser(userId).getAppWidgetIdsForHost(hostId);
- }
-
- @Override
- public void deleteAppWidgetId(int appWidgetId, int userId) throws RemoteException {
- getImplForUser(userId).deleteAppWidgetId(appWidgetId);
- }
-
- @Override
- public void deleteHost(int hostId, int userId) throws RemoteException {
- getImplForUser(userId).deleteHost(hostId);
- }
-
- @Override
- public void deleteAllHosts(int userId) throws RemoteException {
- getImplForUser(userId).deleteAllHosts();
- }
-
- @Override
- public void bindAppWidgetId(int appWidgetId, ComponentName provider, Bundle options, int userId)
- throws RemoteException {
- getImplForUser(userId).bindAppWidgetId(appWidgetId, provider, options);
- }
-
- @Override
- public boolean bindAppWidgetIdIfAllowed(
- String packageName, int appWidgetId, ComponentName provider, Bundle options, int userId)
- throws RemoteException {
- return getImplForUser(userId).bindAppWidgetIdIfAllowed(
- packageName, appWidgetId, provider, options);
- }
-
- @Override
- public boolean hasBindAppWidgetPermission(String packageName, int userId)
- throws RemoteException {
- return getImplForUser(userId).hasBindAppWidgetPermission(packageName);
- }
-
- @Override
- public void setBindAppWidgetPermission(String packageName, boolean permission, int userId)
- throws RemoteException {
- getImplForUser(userId).setBindAppWidgetPermission(packageName, permission);
- }
-
- @Override
- public void bindRemoteViewsService(int appWidgetId, Intent intent, IBinder connection,
- int userId) throws RemoteException {
- getImplForUser(userId).bindRemoteViewsService(appWidgetId, intent, connection);
- }
-
- @Override
- public int[] startListening(IAppWidgetHost host, String packageName, int hostId,
- List<RemoteViews> updatedViews, int userId) throws RemoteException {
- return getImplForUser(userId).startListening(host, packageName, hostId, updatedViews);
- }
-
- public void onUserRemoved(int userId) {
- if (userId < 1) return;
- synchronized (mAppWidgetServices) {
- AppWidgetServiceImpl impl = mAppWidgetServices.get(userId);
- mAppWidgetServices.remove(userId);
-
- if (impl == null) {
- AppWidgetServiceImpl.getSettingsFile(userId).delete();
- } else {
- impl.onUserRemoved();
- }
- }
- }
-
- public void onUserStopping(int userId) {
- if (userId < 1) return;
- synchronized (mAppWidgetServices) {
- AppWidgetServiceImpl impl = mAppWidgetServices.get(userId);
- if (impl != null) {
- mAppWidgetServices.remove(userId);
- impl.onUserStopping();
- }
- }
- }
-
- private void checkPermission(int userId) {
- int realUserId = ActivityManager.handleIncomingUser(
- Binder.getCallingPid(),
- Binder.getCallingUid(),
- userId,
- false, /* allowAll */
- true, /* requireFull */
- this.getClass().getSimpleName(),
- this.getClass().getPackage().getName());
- }
-
- private AppWidgetServiceImpl getImplForUser(int userId) {
- checkPermission(userId);
- boolean sendInitial = false;
- AppWidgetServiceImpl service;
- synchronized (mAppWidgetServices) {
- service = mAppWidgetServices.get(userId);
- if (service == null) {
- Slog.i(TAG, "Unable to find AppWidgetServiceImpl for user " + userId + ", adding");
- // TODO: Verify that it's a valid user
- service = new AppWidgetServiceImpl(mContext, userId, mSaveStateHandler);
- service.systemReady(mSafeMode);
- // Assume that BOOT_COMPLETED was received, as this is a non-primary user.
- mAppWidgetServices.append(userId, service);
- sendInitial = true;
- }
- }
- if (sendInitial) {
- service.sendInitialBroadcasts();
- }
- return service;
- }
-
- @Override
- public int[] getAppWidgetIds(ComponentName provider, int userId) throws RemoteException {
- return getImplForUser(userId).getAppWidgetIds(provider);
- }
-
- @Override
- public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId, int userId)
- throws RemoteException {
- return getImplForUser(userId).getAppWidgetInfo(appWidgetId);
- }
-
- @Override
- public RemoteViews getAppWidgetViews(int appWidgetId, int userId) throws RemoteException {
- return getImplForUser(userId).getAppWidgetViews(appWidgetId);
- }
-
- @Override
- public void updateAppWidgetOptions(int appWidgetId, Bundle options, int userId) {
- getImplForUser(userId).updateAppWidgetOptions(appWidgetId, options);
- }
-
- @Override
- public Bundle getAppWidgetOptions(int appWidgetId, int userId) {
- return getImplForUser(userId).getAppWidgetOptions(appWidgetId);
- }
-
- @Override
- public List<AppWidgetProviderInfo> getInstalledProviders(int categoryFilter, int userId)
- throws RemoteException {
- return getImplForUser(userId).getInstalledProviders(categoryFilter);
- }
-
- @Override
- public void notifyAppWidgetViewDataChanged(int[] appWidgetIds, int viewId, int userId)
- throws RemoteException {
- getImplForUser(userId).notifyAppWidgetViewDataChanged(
- appWidgetIds, viewId);
- }
-
- @Override
- public void partiallyUpdateAppWidgetIds(int[] appWidgetIds, RemoteViews views, int userId)
- throws RemoteException {
- getImplForUser(userId).partiallyUpdateAppWidgetIds(
- appWidgetIds, views);
- }
-
- @Override
- public void stopListening(int hostId, int userId) throws RemoteException {
- getImplForUser(userId).stopListening(hostId);
- }
-
- @Override
- public void unbindRemoteViewsService(int appWidgetId, Intent intent, int userId)
- throws RemoteException {
- getImplForUser(userId).unbindRemoteViewsService(
- appWidgetId, intent);
- }
-
- @Override
- public void updateAppWidgetIds(int[] appWidgetIds, RemoteViews views, int userId)
- throws RemoteException {
- getImplForUser(userId).updateAppWidgetIds(appWidgetIds, views);
- }
-
- @Override
- public void updateAppWidgetProvider(ComponentName provider, RemoteViews views, int userId)
- throws RemoteException {
- getImplForUser(userId).updateAppWidgetProvider(provider, views);
- }
-
- @Override
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
-
- // Dump the state of all the app widget providers
- synchronized (mAppWidgetServices) {
- IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
- for (int i = 0; i < mAppWidgetServices.size(); i++) {
- pw.println("User: " + mAppWidgetServices.keyAt(i));
- ipw.increaseIndent();
- AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i);
- service.dump(fd, ipw, args);
- ipw.decreaseIndent();
- }
- }
- }
-
- BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- // Slog.d(TAG, "received " + action);
- if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
- int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
- if (userId >= 0) {
- getImplForUser(userId).sendInitialBroadcasts();
- } else {
- Slog.w(TAG, "Incorrect user handle supplied in " + intent);
- }
- } else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
- for (int i = 0; i < mAppWidgetServices.size(); i++) {
- AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i);
- service.onConfigurationChanged();
- }
- } else {
- int sendingUser = getSendingUserId();
- if (sendingUser == UserHandle.USER_ALL) {
- for (int i = 0; i < mAppWidgetServices.size(); i++) {
- AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i);
- service.onBroadcastReceived(intent);
- }
- } else {
- AppWidgetServiceImpl service = mAppWidgetServices.get(sendingUser);
- if (service != null) {
- service.onBroadcastReceived(intent);
- }
- }
- }
- }
- };
-}
diff --git a/services/java/com/android/server/display/DisplayTransactionListener.java b/services/java/com/android/server/display/DisplayTransactionListener.java
deleted file mode 100644
index 34eb8f9..0000000
--- a/services/java/com/android/server/display/DisplayTransactionListener.java
+++ /dev/null
@@ -1,26 +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.server.display;
-
-/**
- * Called within a Surface transaction whenever the size or orientation of a
- * display may have changed. Provides an opportunity for the client to
- * update the position of its surfaces as part of the same transaction.
- */
-public interface DisplayTransactionListener {
- void onDisplayTransaction();
-}
diff --git a/services/java/com/android/server/display/HeadlessDisplayAdapter.java b/services/java/com/android/server/display/HeadlessDisplayAdapter.java
deleted file mode 100644
index 7a104d7..0000000
--- a/services/java/com/android/server/display/HeadlessDisplayAdapter.java
+++ /dev/null
@@ -1,73 +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.server.display;
-
-import android.content.Context;
-import android.os.Handler;
-import android.util.DisplayMetrics;
-import android.view.Display;
-
-/**
- * Provides a fake default display for headless systems.
- * <p>
- * Display adapters are guarded by the {@link DisplayManagerService.SyncRoot} lock.
- * </p>
- */
-final class HeadlessDisplayAdapter extends DisplayAdapter {
- private static final String TAG = "HeadlessDisplayAdapter";
-
- // Called with SyncRoot lock held.
- public HeadlessDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
- Context context, Handler handler, Listener listener) {
- super(syncRoot, context, handler, listener, TAG);
- }
-
- @Override
- public void registerLocked() {
- super.registerLocked();
- sendDisplayDeviceEventLocked(new HeadlessDisplayDevice(), DISPLAY_DEVICE_EVENT_ADDED);
- }
-
- private final class HeadlessDisplayDevice extends DisplayDevice {
- private DisplayDeviceInfo mInfo;
-
- public HeadlessDisplayDevice() {
- super(HeadlessDisplayAdapter.this, null);
- }
-
- @Override
- public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
- if (mInfo == null) {
- mInfo = new DisplayDeviceInfo();
- mInfo.name = getContext().getResources().getString(
- com.android.internal.R.string.display_manager_built_in_display_name);
- mInfo.width = 640;
- mInfo.height = 480;
- mInfo.refreshRate = 60;
- mInfo.densityDpi = DisplayMetrics.DENSITY_DEFAULT;
- mInfo.xDpi = 160;
- mInfo.yDpi = 160;
- mInfo.flags = DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY
- | DisplayDeviceInfo.FLAG_SECURE
- | DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS;
- mInfo.type = Display.TYPE_BUILT_IN;
- mInfo.touch = DisplayDeviceInfo.TOUCH_NONE;
- }
- return mInfo;
- }
- }
-}
diff --git a/services/java/com/android/server/print/PrintManagerService.java b/services/java/com/android/server/print/PrintManagerService.java
deleted file mode 100644
index 98acc27..0000000
--- a/services/java/com/android/server/print/PrintManagerService.java
+++ /dev/null
@@ -1,656 +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.server.print;
-
-import android.Manifest;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.ServiceInfo;
-import android.database.ContentObserver;
-import android.net.Uri;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.Process;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.print.IPrintDocumentAdapter;
-import android.print.IPrintJobStateChangeListener;
-import android.print.IPrintManager;
-import android.print.IPrinterDiscoveryObserver;
-import android.print.PrintAttributes;
-import android.print.PrintJobId;
-import android.print.PrintJobInfo;
-import android.print.PrinterId;
-import android.printservice.PrintServiceInfo;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.SparseArray;
-
-import com.android.internal.R;
-import com.android.internal.content.PackageMonitor;
-import com.android.internal.os.BackgroundThread;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-
-public final class PrintManagerService extends IPrintManager.Stub {
-
- private static final char COMPONENT_NAME_SEPARATOR = ':';
-
- private static final String EXTRA_PRINT_SERVICE_COMPONENT_NAME =
- "EXTRA_PRINT_SERVICE_COMPONENT_NAME";
-
- private final Object mLock = new Object();
-
- private final Context mContext;
-
- private final SparseArray<UserState> mUserStates = new SparseArray<UserState>();
-
- private int mCurrentUserId = UserHandle.USER_OWNER;
-
- public PrintManagerService(Context context) {
- mContext = context;
- registerContentObservers();
- registerBoradcastReceivers();
- }
-
- public void systemRuning() {
- BackgroundThread.getHandler().post(new Runnable() {
- @Override
- public void run() {
- final UserState userState;
- synchronized (mLock) {
- userState = getCurrentUserStateLocked();
- userState.updateIfNeededLocked();
- }
- // This is the first time we switch to this user after boot, so
- // now is the time to remove obsolete print jobs since they
- // are from the last boot and no application would query them.
- userState.removeObsoletePrintJobs();
- }
- });
- }
-
- @Override
- public Bundle print(String printJobName, IPrintDocumentAdapter adapter,
- PrintAttributes attributes, String packageName, int appId, int userId) {
- final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
- final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
- String resolvedPackageName = resolveCallingPackageNameEnforcingSecurity(packageName);
- final UserState userState;
- synchronized (mLock) {
- userState = getOrCreateUserStateLocked(resolvedUserId);
- }
- final long identity = Binder.clearCallingIdentity();
- try {
- return userState.print(printJobName, adapter, attributes,
- resolvedPackageName, resolvedAppId);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
- @Override
- public List<PrintJobInfo> getPrintJobInfos(int appId, int userId) {
- final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
- final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
- final UserState userState;
- synchronized (mLock) {
- userState = getOrCreateUserStateLocked(resolvedUserId);
- }
- final long identity = Binder.clearCallingIdentity();
- try {
- return userState.getPrintJobInfos(resolvedAppId);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
- @Override
- public PrintJobInfo getPrintJobInfo(PrintJobId printJobId, int appId, int userId) {
- final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
- final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
- final UserState userState;
- synchronized (mLock) {
- userState = getOrCreateUserStateLocked(resolvedUserId);
- }
- final long identity = Binder.clearCallingIdentity();
- try {
- return userState.getPrintJobInfo(printJobId, resolvedAppId);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
- @Override
- public void cancelPrintJob(PrintJobId printJobId, int appId, int userId) {
- final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
- final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
- final UserState userState;
- synchronized (mLock) {
- userState = getOrCreateUserStateLocked(resolvedUserId);
- }
- final long identity = Binder.clearCallingIdentity();
- try {
- userState.cancelPrintJob(printJobId, resolvedAppId);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
- @Override
- public void restartPrintJob(PrintJobId printJobId, int appId, int userId) {
- final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
- final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
- final UserState userState;
- synchronized (mLock) {
- userState = getOrCreateUserStateLocked(resolvedUserId);
- }
- final long identity = Binder.clearCallingIdentity();
- try {
- userState.restartPrintJob(printJobId, resolvedAppId);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
- @Override
- public List<PrintServiceInfo> getEnabledPrintServices(int userId) {
- final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
- final UserState userState;
- synchronized (mLock) {
- userState = getOrCreateUserStateLocked(resolvedUserId);
- }
- final long identity = Binder.clearCallingIdentity();
- try {
- return userState.getEnabledPrintServices();
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
- @Override
- public List<PrintServiceInfo> getInstalledPrintServices(int userId) {
- final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
- final UserState userState;
- synchronized (mLock) {
- userState = getOrCreateUserStateLocked(resolvedUserId);
- }
- final long identity = Binder.clearCallingIdentity();
- try {
- return userState.getInstalledPrintServices();
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
- @Override
- public void createPrinterDiscoverySession(IPrinterDiscoveryObserver observer,
- int userId) {
- final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
- final UserState userState;
- synchronized (mLock) {
- userState = getOrCreateUserStateLocked(resolvedUserId);
- }
- final long identity = Binder.clearCallingIdentity();
- try {
- userState.createPrinterDiscoverySession(observer);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
- @Override
- public void destroyPrinterDiscoverySession(IPrinterDiscoveryObserver observer,
- int userId) {
- final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
- final UserState userState;
- synchronized (mLock) {
- userState = getOrCreateUserStateLocked(resolvedUserId);
- }
- final long identity = Binder.clearCallingIdentity();
- try {
- userState.destroyPrinterDiscoverySession(observer);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
- @Override
- public void startPrinterDiscovery(IPrinterDiscoveryObserver observer,
- List<PrinterId> priorityList, int userId) {
- final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
- final UserState userState;
- synchronized (mLock) {
- userState = getOrCreateUserStateLocked(resolvedUserId);
- }
- final long identity = Binder.clearCallingIdentity();
- try {
- userState.startPrinterDiscovery(observer, priorityList);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
- @Override
- public void stopPrinterDiscovery(IPrinterDiscoveryObserver observer, int userId) {
- final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
- final UserState userState;
- synchronized (mLock) {
- userState = getOrCreateUserStateLocked(resolvedUserId);
- }
- final long identity = Binder.clearCallingIdentity();
- try {
- userState.stopPrinterDiscovery(observer);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
- @Override
- public void validatePrinters(List<PrinterId> printerIds, int userId) {
- final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
- final UserState userState;
- synchronized (mLock) {
- userState = getOrCreateUserStateLocked(resolvedUserId);
- }
- final long identity = Binder.clearCallingIdentity();
- try {
- userState.validatePrinters(printerIds);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
- @Override
- public void startPrinterStateTracking(PrinterId printerId, int userId) {
- final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
- final UserState userState;
- synchronized (mLock) {
- userState = getOrCreateUserStateLocked(resolvedUserId);
- }
- final long identity = Binder.clearCallingIdentity();
- try {
- userState.startPrinterStateTracking(printerId);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
- @Override
- public void stopPrinterStateTracking(PrinterId printerId, int userId) {
- final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
- final UserState userState;
- synchronized (mLock) {
- userState = getOrCreateUserStateLocked(resolvedUserId);
- }
- final long identity = Binder.clearCallingIdentity();
- try {
- userState.stopPrinterStateTracking(printerId);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
- @Override
- public void addPrintJobStateChangeListener(IPrintJobStateChangeListener listener,
- int appId, int userId) throws RemoteException {
- final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
- final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
- final UserState userState;
- synchronized (mLock) {
- userState = getOrCreateUserStateLocked(resolvedUserId);
- }
- final long identity = Binder.clearCallingIdentity();
- try {
- userState.addPrintJobStateChangeListener(listener, resolvedAppId);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
- @Override
- public void removePrintJobStateChangeListener(IPrintJobStateChangeListener listener,
- int userId) {
- final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
- final UserState userState;
- synchronized (mLock) {
- userState = getOrCreateUserStateLocked(resolvedUserId);
- }
- final long identity = Binder.clearCallingIdentity();
- try {
- userState.removePrintJobStateChangeListener(listener);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
- @Override
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump PrintManager from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
-
- synchronized (mLock) {
- final long identity = Binder.clearCallingIdentity();
- try {
- pw.println("PRINT MANAGER STATE (dumpsys print)");
- final int userStateCount = mUserStates.size();
- for (int i = 0; i < userStateCount; i++) {
- UserState userState = mUserStates.valueAt(i);
- userState.dump(fd, pw, "");
- pw.println();
- }
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
- }
-
- private void registerContentObservers() {
- final Uri enabledPrintServicesUri = Settings.Secure.getUriFor(
- Settings.Secure.ENABLED_PRINT_SERVICES);
-
- ContentObserver observer = new ContentObserver(BackgroundThread.getHandler()) {
- @Override
- public void onChange(boolean selfChange, Uri uri) {
- if (enabledPrintServicesUri.equals(uri)) {
- synchronized (mLock) {
- UserState userState = getCurrentUserStateLocked();
- userState.updateIfNeededLocked();
- }
- }
- }
- };
-
- mContext.getContentResolver().registerContentObserver(enabledPrintServicesUri,
- false, observer, UserHandle.USER_ALL);
- }
-
- private void registerBoradcastReceivers() {
- PackageMonitor monitor = new PackageMonitor() {
- @Override
- public boolean onPackageChanged(String packageName, int uid, String[] components) {
- synchronized (mLock) {
- UserState userState = getOrCreateUserStateLocked(getChangingUserId());
- Iterator<ComponentName> iterator = userState.getEnabledServices().iterator();
- while (iterator.hasNext()) {
- ComponentName componentName = iterator.next();
- if (packageName.equals(componentName.getPackageName())) {
- userState.updateIfNeededLocked();
- return true;
- }
- }
- }
- return false;
- }
-
- @Override
- public void onPackageRemoved(String packageName, int uid) {
- synchronized (mLock) {
- UserState userState = getOrCreateUserStateLocked(getChangingUserId());
- Iterator<ComponentName> iterator = userState.getEnabledServices().iterator();
- while (iterator.hasNext()) {
- ComponentName componentName = iterator.next();
- if (packageName.equals(componentName.getPackageName())) {
- iterator.remove();
- persistComponentNamesToSettingLocked(
- Settings.Secure.ENABLED_PRINT_SERVICES,
- userState.getEnabledServices(), getChangingUserId());
- userState.updateIfNeededLocked();
- return;
- }
- }
- }
- }
-
- @Override
- public boolean onHandleForceStop(Intent intent, String[] stoppedPackages,
- int uid, boolean doit) {
- synchronized (mLock) {
- UserState userState = getOrCreateUserStateLocked(getChangingUserId());
- boolean stoppedSomePackages = false;
- Iterator<ComponentName> iterator = userState.getEnabledServices().iterator();
- while (iterator.hasNext()) {
- ComponentName componentName = iterator.next();
- String componentPackage = componentName.getPackageName();
- for (String stoppedPackage : stoppedPackages) {
- if (componentPackage.equals(stoppedPackage)) {
- if (!doit) {
- return true;
- }
- stoppedSomePackages = true;
- break;
- }
- }
- }
- if (stoppedSomePackages) {
- userState.updateIfNeededLocked();
- }
- return false;
- }
- }
-
- @Override
- public void onPackageAdded(String packageName, int uid) {
- Intent intent = new Intent(android.printservice.PrintService.SERVICE_INTERFACE);
- intent.setPackage(packageName);
-
- List<ResolveInfo> installedServices = mContext.getPackageManager()
- .queryIntentServicesAsUser(intent, PackageManager.GET_SERVICES,
- getChangingUserId());
-
- if (installedServices == null) {
- return;
- }
-
- final int installedServiceCount = installedServices.size();
- for (int i = 0; i < installedServiceCount; i++) {
- ServiceInfo serviceInfo = installedServices.get(i).serviceInfo;
- ComponentName component = new ComponentName(serviceInfo.packageName,
- serviceInfo.name);
- String label = serviceInfo.loadLabel(mContext.getPackageManager()).toString();
- showEnableInstalledPrintServiceNotification(component, label,
- getChangingUserId());
- }
- }
-
- private void persistComponentNamesToSettingLocked(String settingName,
- Set<ComponentName> componentNames, int userId) {
- StringBuilder builder = new StringBuilder();
- for (ComponentName componentName : componentNames) {
- if (builder.length() > 0) {
- builder.append(COMPONENT_NAME_SEPARATOR);
- }
- builder.append(componentName.flattenToShortString());
- }
- Settings.Secure.putStringForUser(mContext.getContentResolver(),
- settingName, builder.toString(), userId);
- }
- };
-
- // package changes
- monitor.register(mContext, BackgroundThread.getHandler().getLooper(),
- UserHandle.ALL, true);
-
- // user changes
- IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
- intentFilter.addAction(Intent.ACTION_USER_REMOVED);
-
- mContext.registerReceiverAsUser(new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (Intent.ACTION_USER_SWITCHED.equals(action)) {
- switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
- } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
- removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
- }
- }
- }, UserHandle.ALL, intentFilter, null, BackgroundThread.getHandler());
- }
-
- private UserState getCurrentUserStateLocked() {
- return getOrCreateUserStateLocked(mCurrentUserId);
- }
-
- private UserState getOrCreateUserStateLocked(int userId) {
- UserState userState = mUserStates.get(userId);
- if (userState == null) {
- userState = new UserState(mContext, userId, mLock);
- mUserStates.put(userId, userState);
- }
- return userState;
- }
-
- private void switchUser(int newUserId) {
- UserState userState;
- synchronized (mLock) {
- if (newUserId == mCurrentUserId) {
- return;
- }
- mCurrentUserId = newUserId;
- userState = mUserStates.get(mCurrentUserId);
- if (userState == null) {
- userState = getCurrentUserStateLocked();
- userState.updateIfNeededLocked();
- } else {
- userState.updateIfNeededLocked();
- }
- }
- // This is the first time we switch to this user after boot, so
- // now is the time to remove obsolete print jobs since they
- // are from the last boot and no application would query them.
- userState.removeObsoletePrintJobs();
- }
-
- private void removeUser(int removedUserId) {
- synchronized (mLock) {
- UserState userState = mUserStates.get(removedUserId);
- if (userState != null) {
- userState.destroyLocked();
- mUserStates.remove(removedUserId);
- }
- }
- }
-
- private int resolveCallingAppEnforcingPermissions(int appId) {
- final int callingUid = Binder.getCallingUid();
- if (callingUid == 0 || callingUid == Process.SYSTEM_UID
- || callingUid == Process.SHELL_UID) {
- return appId;
- }
- final int callingAppId = UserHandle.getAppId(callingUid);
- if (appId == callingAppId) {
- return appId;
- }
- if (mContext.checkCallingPermission(
- "com.android.printspooler.permission.ACCESS_ALL_PRINT_JOBS")
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Call from app " + callingAppId + " as app "
- + appId + " without com.android.printspooler.permission"
- + ".ACCESS_ALL_PRINT_JOBS");
- }
- return appId;
- }
-
- private int resolveCallingUserEnforcingPermissions(int userId) {
- final int callingUid = Binder.getCallingUid();
- if (callingUid == 0 || callingUid == Process.SYSTEM_UID
- || callingUid == Process.SHELL_UID) {
- return userId;
- }
- final int callingUserId = UserHandle.getUserId(callingUid);
- if (callingUserId == userId) {
- return userId;
- }
- if (mContext.checkCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL)
- != PackageManager.PERMISSION_GRANTED
- || mContext.checkCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS)
- != PackageManager.PERMISSION_GRANTED) {
- if (userId == UserHandle.USER_CURRENT_OR_SELF) {
- return callingUserId;
- }
- throw new SecurityException("Call from user " + callingUserId + " as user "
- + userId + " without permission INTERACT_ACROSS_USERS or "
- + "INTERACT_ACROSS_USERS_FULL not allowed.");
- }
- if (userId == UserHandle.USER_CURRENT || userId == UserHandle.USER_CURRENT_OR_SELF) {
- return mCurrentUserId;
- }
- throw new IllegalArgumentException("Calling user can be changed to only "
- + "UserHandle.USER_CURRENT or UserHandle.USER_CURRENT_OR_SELF.");
- }
-
- private String resolveCallingPackageNameEnforcingSecurity(String packageName) {
- if (TextUtils.isEmpty(packageName)) {
- return null;
- }
- String[] packages = mContext.getPackageManager().getPackagesForUid(
- Binder.getCallingUid());
- final int packageCount = packages.length;
- for (int i = 0; i < packageCount; i++) {
- if (packageName.equals(packages[i])) {
- return packageName;
- }
- }
- return null;
- }
-
- private void showEnableInstalledPrintServiceNotification(ComponentName component,
- String label, int userId) {
- UserHandle userHandle = new UserHandle(userId);
-
- Intent intent = new Intent(Settings.ACTION_PRINT_SETTINGS);
- intent.putExtra(EXTRA_PRINT_SERVICE_COMPONENT_NAME, component.flattenToString());
-
- PendingIntent pendingIntent = PendingIntent.getActivityAsUser(mContext, 0, intent,
- PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_CANCEL_CURRENT, null, userHandle);
-
- Notification.Builder builder = new Notification.Builder(mContext)
- .setSmallIcon(R.drawable.ic_print)
- .setContentTitle(mContext.getString(R.string.print_service_installed_title, label))
- .setContentText(mContext.getString(R.string.print_service_installed_message))
- .setContentIntent(pendingIntent)
- .setWhen(System.currentTimeMillis())
- .setAutoCancel(true)
- .setShowWhen(true);
-
- NotificationManager notificationManager = (NotificationManager) mContext
- .getSystemService(Context.NOTIFICATION_SERVICE);
-
- String notificationTag = getClass().getName() + ":" + component.flattenToString();
- notificationManager.notifyAsUser(notificationTag, 0, builder.build(),
- userHandle);
- }
-}
diff --git a/services/java/com/android/server/wm/DisplayContent.java b/services/java/com/android/server/wm/DisplayContent.java
deleted file mode 100644
index d358b4c..0000000
--- a/services/java/com/android/server/wm/DisplayContent.java
+++ /dev/null
@@ -1,523 +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.server.wm;
-
-import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
-import static com.android.server.wm.WindowManagerService.DEBUG_STACK;
-import static com.android.server.wm.WindowManagerService.DEBUG_VISIBILITY;
-import static com.android.server.wm.WindowManagerService.TAG;
-
-import android.app.ActivityManager.StackBoxInfo;
-import android.graphics.Rect;
-import android.graphics.Region;
-import android.os.Debug;
-import android.util.EventLog;
-import android.util.Slog;
-import android.view.Display;
-import android.view.DisplayInfo;
-import com.android.server.EventLogTags;
-
-import java.io.PrintWriter;
-import java.util.ArrayList;
-
-class DisplayContentList extends ArrayList<DisplayContent> {
-}
-
-/**
- * Utility class for keeping track of the WindowStates and other pertinent contents of a
- * particular Display.
- *
- * IMPORTANT: No method from this class should ever be used without holding
- * WindowManagerService.mWindowMap.
- */
-class DisplayContent {
-
- /** Unique identifier of this stack. */
- private final int mDisplayId;
-
- /** Z-ordered (bottom-most first) list of all Window objects. Assigned to an element
- * from mDisplayWindows; */
- private WindowList mWindows = new WindowList();
-
- // This protects the following display size properties, so that
- // getDisplaySize() doesn't need to acquire the global lock. This is
- // needed because the window manager sometimes needs to use ActivityThread
- // while it has its global state locked (for example to load animation
- // resources), but the ActivityThread also needs get the current display
- // size sometimes when it has its package lock held.
- //
- // These will only be modified with both mWindowMap and mDisplaySizeLock
- // held (in that order) so the window manager doesn't need to acquire this
- // lock when needing these values in its normal operation.
- final Object mDisplaySizeLock = new Object();
- int mInitialDisplayWidth = 0;
- int mInitialDisplayHeight = 0;
- int mInitialDisplayDensity = 0;
- int mBaseDisplayWidth = 0;
- int mBaseDisplayHeight = 0;
- int mBaseDisplayDensity = 0;
- private final DisplayInfo mDisplayInfo = new DisplayInfo();
- private final Display mDisplay;
-
- Rect mBaseDisplayRect = new Rect();
-
- // Accessed directly by all users.
- boolean layoutNeeded;
- int pendingLayoutChanges;
- final boolean isDefaultDisplay;
-
- /**
- * Window tokens that are in the process of exiting, but still
- * on screen for animations.
- */
- final ArrayList<WindowToken> mExitingTokens = new ArrayList<WindowToken>();
-
- /**
- * Application tokens that are in the process of exiting, but still
- * on screen for animations.
- */
- final AppTokenList mExitingAppTokens = new AppTokenList();
-
- /** Array containing the home StackBox and possibly one more which would contain apps. Array
- * is stored in display order with the current bottom stack at 0. */
- private ArrayList<StackBox> mStackBoxes = new ArrayList<StackBox>();
-
- /** True when the home StackBox is at the top of mStackBoxes, false otherwise. */
- private TaskStack mHomeStack = null;
-
- /** Detect user tapping outside of current focused stack bounds .*/
- StackTapPointerEventListener mTapDetector;
-
- /** Detect user tapping outside of current focused stack bounds .*/
- Region mTouchExcludeRegion = new Region();
-
- /** Save allocating when retrieving tasks */
- private ArrayList<Task> mTaskHistory = new ArrayList<Task>();
-
- /** Save allocating when calculating rects */
- Rect mTmpRect = new Rect();
-
- final WindowManagerService mService;
-
- /**
- * @param display May not be null.
- * @param service TODO(cmautner):
- */
- DisplayContent(Display display, WindowManagerService service) {
- mDisplay = display;
- mDisplayId = display.getDisplayId();
- display.getDisplayInfo(mDisplayInfo);
- isDefaultDisplay = mDisplayId == Display.DEFAULT_DISPLAY;
- mService = service;
-
- StackBox newBox = new StackBox(service, this, null);
- mStackBoxes.add(newBox);
- TaskStack newStack = new TaskStack(service, HOME_STACK_ID, this);
- newStack.mStackBox = newBox;
- newBox.mStack = newStack;
- mHomeStack = newStack;
- }
-
- int getDisplayId() {
- return mDisplayId;
- }
-
- WindowList getWindowList() {
- return mWindows;
- }
-
- Display getDisplay() {
- return mDisplay;
- }
-
- DisplayInfo getDisplayInfo() {
- return mDisplayInfo;
- }
-
- /**
- * Returns true if the specified UID has access to this display.
- */
- public boolean hasAccess(int uid) {
- return mDisplay.hasAccess(uid);
- }
-
- boolean homeOnTop() {
- return mStackBoxes.get(0).mStack != mHomeStack;
- }
-
- public boolean isPrivate() {
- return (mDisplay.getFlags() & Display.FLAG_PRIVATE) != 0;
- }
-
- /**
- * Retrieve the tasks on this display in stack order from the bottommost TaskStack up.
- * @return All the Tasks, in order, on this display.
- */
- ArrayList<Task> getTasks() {
- return mTaskHistory;
- }
-
- void addTask(Task task, boolean toTop) {
- mTaskHistory.remove(task);
-
- final int userId = task.mUserId;
- int taskNdx;
- final int numTasks = mTaskHistory.size();
- if (toTop) {
- for (taskNdx = numTasks - 1; taskNdx >= 0; --taskNdx) {
- if (mTaskHistory.get(taskNdx).mUserId == userId) {
- break;
- }
- }
- ++taskNdx;
- } else {
- for (taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
- if (mTaskHistory.get(taskNdx).mUserId == userId) {
- break;
- }
- }
- }
-
- mTaskHistory.add(taskNdx, task);
- EventLog.writeEvent(EventLogTags.WM_TASK_MOVED, task.taskId, toTop ? 1 : 0, taskNdx);
- }
-
- void removeTask(Task task) {
- mTaskHistory.remove(task);
- }
-
- TaskStack getHomeStack() {
- return mHomeStack;
- }
-
- void updateDisplayInfo() {
- mDisplay.getDisplayInfo(mDisplayInfo);
- }
-
- void getLogicalDisplayRect(Rect out) {
- updateDisplayInfo();
- // Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked.
- int width = mDisplayInfo.logicalWidth;
- int left = (mBaseDisplayWidth - width) / 2;
- int height = mDisplayInfo.logicalHeight;
- int top = (mBaseDisplayHeight - height) / 2;
- out.set(left, top, left + width, top + height);
- }
-
- /** @return The number of tokens in all of the Tasks on this display. */
- int numTokens() {
- int count = 0;
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- count += mTaskHistory.get(taskNdx).mAppTokens.size();
- }
- return count;
- }
-
- /** Refer to {@link WindowManagerService#createStack(int, int, int, float)} */
- TaskStack createStack(int stackId, int relativeStackBoxId, int position, float weight) {
- TaskStack newStack = null;
- if (DEBUG_STACK) Slog.d(TAG, "createStack: stackId=" + stackId + " relativeStackBoxId="
- + relativeStackBoxId + " position=" + position + " weight=" + weight);
- if (stackId == HOME_STACK_ID) {
- if (mStackBoxes.size() != 1) {
- throw new IllegalArgumentException("createStack: HOME_STACK_ID (0) not first.");
- }
- newStack = mHomeStack;
- } else {
- int stackBoxNdx;
- for (stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
- final StackBox box = mStackBoxes.get(stackBoxNdx);
- if (position == StackBox.TASK_STACK_GOES_OVER
- || position == StackBox.TASK_STACK_GOES_UNDER) {
- // Position indicates a new box is added at top level only.
- if (box.contains(relativeStackBoxId)) {
- StackBox newBox = new StackBox(mService, this, null);
- newStack = new TaskStack(mService, stackId, this);
- newStack.mStackBox = newBox;
- newBox.mStack = newStack;
- final int offset = position == StackBox.TASK_STACK_GOES_OVER ? 1 : 0;
- if (DEBUG_STACK) Slog.d(TAG, "createStack: inserting stack at " +
- (stackBoxNdx + offset));
- mStackBoxes.add(stackBoxNdx + offset, newBox);
- break;
- }
- } else {
- // Remaining position values indicate a box must be split.
- newStack = box.split(stackId, relativeStackBoxId, position, weight);
- if (newStack != null) {
- break;
- }
- }
- }
- if (stackBoxNdx < 0) {
- throw new IllegalArgumentException("createStack: stackBoxId " + relativeStackBoxId
- + " not found.");
- }
- }
- if (newStack != null) {
- layoutNeeded = true;
- }
- EventLog.writeEvent(EventLogTags.WM_STACK_CREATED, stackId, relativeStackBoxId, position,
- (int)(weight * 100 + 0.5));
- return newStack;
- }
-
- /** Refer to {@link WindowManagerService#resizeStackBox(int, float)} */
- boolean resizeStack(int stackBoxId, float weight) {
- for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
- final StackBox box = mStackBoxes.get(stackBoxNdx);
- if (box.resize(stackBoxId, weight)) {
- layoutNeeded = true;
- return true;
- }
- }
- return false;
- }
-
- void addStackBox(StackBox box, boolean toTop) {
- if (mStackBoxes.size() >= 2) {
- throw new RuntimeException("addStackBox: Too many toplevel StackBoxes!");
- }
- mStackBoxes.add(toTop ? mStackBoxes.size() : 0, box);
- }
-
- void removeStackBox(StackBox box) {
- if (DEBUG_STACK) Slog.d(TAG, "removeStackBox: box=" + box);
- final TaskStack stack = box.mStack;
- if (stack != null && stack.mStackId == HOME_STACK_ID) {
- // Never delete the home stack, even if it is empty.
- if (DEBUG_STACK) Slog.d(TAG, "removeStackBox: Not deleting home stack.");
- return;
- }
- mStackBoxes.remove(box);
- }
-
- StackBoxInfo getStackBoxInfo(StackBox box) {
- StackBoxInfo info = new StackBoxInfo();
- info.stackBoxId = box.mStackBoxId;
- info.weight = box.mWeight;
- info.vertical = box.mVertical;
- info.bounds = new Rect(box.mBounds);
- if (box.mStack != null) {
- info.stackId = box.mStack.mStackId;
- // ActivityManagerService will fill in the StackInfo.
- } else {
- info.stackId = -1;
- info.children = new StackBoxInfo[2];
- info.children[0] = getStackBoxInfo(box.mFirst);
- info.children[1] = getStackBoxInfo(box.mSecond);
- }
- return info;
- }
-
- ArrayList<StackBoxInfo> getStackBoxInfos() {
- ArrayList<StackBoxInfo> list = new ArrayList<StackBoxInfo>();
- for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
- list.add(getStackBoxInfo(mStackBoxes.get(stackBoxNdx)));
- }
- return list;
- }
-
- /**
- * Move the home StackBox to the top or bottom of mStackBoxes. That is the only place
- * it is allowed to be. This is a nop if the home StackBox is already in the correct position.
- * @param toTop Move home to the top of mStackBoxes if true, to the bottom if false.
- * @return true if a change was made, false otherwise.
- */
- boolean moveHomeStackBox(boolean toTop) {
- if (DEBUG_STACK) Slog.d(TAG, "moveHomeStackBox: toTop=" + toTop + " Callers=" +
- Debug.getCallers(4));
- EventLog.writeEvent(EventLogTags.WM_HOME_STACK_MOVED, toTop ? 1 : 0);
- switch (mStackBoxes.size()) {
- case 0: throw new RuntimeException("moveHomeStackBox: No home StackBox!");
- case 1: return false; // Only the home StackBox exists.
- case 2:
- if (homeOnTop() ^ toTop) {
- mStackBoxes.add(mStackBoxes.remove(0));
- return true;
- }
- return false;
- default: throw new RuntimeException("moveHomeStackBox: Too many toplevel StackBoxes!");
- }
- }
-
- /**
- * Propagate the new bounds to all child stack boxes, applying weights as we move down.
- * @param contentRect The bounds to apply at the top level.
- */
- boolean setStackBoxSize(Rect contentRect) {
- boolean change = false;
- for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
- change |= mStackBoxes.get(stackBoxNdx).setStackBoxSizes(contentRect, true);
- }
- return change;
- }
-
- Rect getStackBounds(int stackId) {
- for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
- Rect bounds = mStackBoxes.get(stackBoxNdx).getStackBounds(stackId);
- if (bounds != null) {
- return bounds;
- }
- }
- return null;
- }
-
- int stackIdFromPoint(int x, int y) {
- StackBox topBox = mStackBoxes.get(mStackBoxes.size() - 1);
- return topBox.stackIdFromPoint(x, y);
- }
-
- void setTouchExcludeRegion(TaskStack focusedStack) {
- mTouchExcludeRegion.set(mBaseDisplayRect);
- WindowList windows = getWindowList();
- for (int i = windows.size() - 1; i >= 0; --i) {
- final WindowState win = windows.get(i);
- final TaskStack stack = win.getStack();
- if (win.isVisibleLw() && stack != null && stack != focusedStack) {
- mTmpRect.set(win.mVisibleFrame);
- mTmpRect.intersect(win.mVisibleInsets);
- mTouchExcludeRegion.op(mTmpRect, Region.Op.DIFFERENCE);
- }
- }
- }
-
- void switchUserStacks(int oldUserId, int newUserId) {
- final WindowList windows = getWindowList();
- for (int i = 0; i < windows.size(); i++) {
- final WindowState win = windows.get(i);
- if (win.isHiddenFromUserLocked()) {
- if (DEBUG_VISIBILITY) Slog.w(TAG, "user changing " + newUserId + " hiding "
- + win + ", attrs=" + win.mAttrs.type + ", belonging to "
- + win.mOwnerUid);
- win.hideLw(false);
- }
- }
-
- for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
- mStackBoxes.get(stackBoxNdx).switchUserStacks(newUserId);
- }
- }
-
- void resetAnimationBackgroundAnimator() {
- for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
- mStackBoxes.get(stackBoxNdx).resetAnimationBackgroundAnimator();
- }
- }
-
- boolean animateDimLayers() {
- boolean result = false;
- for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
- result |= mStackBoxes.get(stackBoxNdx).animateDimLayers();
- }
- return result;
- }
-
- void resetDimming() {
- for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
- mStackBoxes.get(stackBoxNdx).resetDimming();
- }
- }
-
- boolean isDimming() {
- boolean result = false;
- for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
- result |= mStackBoxes.get(stackBoxNdx).isDimming();
- }
- return result;
- }
-
- void stopDimmingIfNeeded() {
- for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
- mStackBoxes.get(stackBoxNdx).stopDimmingIfNeeded();
- }
- }
-
- void close() {
- for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
- mStackBoxes.get(stackBoxNdx).close();
- }
- }
-
- public void dump(String prefix, PrintWriter pw) {
- pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId);
- final String subPrefix = " " + prefix;
- pw.print(subPrefix); pw.print("init="); pw.print(mInitialDisplayWidth); pw.print("x");
- pw.print(mInitialDisplayHeight); pw.print(" "); pw.print(mInitialDisplayDensity);
- pw.print("dpi");
- if (mInitialDisplayWidth != mBaseDisplayWidth
- || mInitialDisplayHeight != mBaseDisplayHeight
- || mInitialDisplayDensity != mBaseDisplayDensity) {
- pw.print(" base=");
- pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight);
- pw.print(" "); pw.print(mBaseDisplayDensity); pw.print("dpi");
- }
- pw.print(" cur=");
- pw.print(mDisplayInfo.logicalWidth);
- pw.print("x"); pw.print(mDisplayInfo.logicalHeight);
- pw.print(" app=");
- pw.print(mDisplayInfo.appWidth);
- pw.print("x"); pw.print(mDisplayInfo.appHeight);
- pw.print(" rng="); pw.print(mDisplayInfo.smallestNominalAppWidth);
- pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight);
- pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth);
- pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight);
- pw.print(subPrefix); pw.print("layoutNeeded="); pw.println(layoutNeeded);
- for (int boxNdx = 0; boxNdx < mStackBoxes.size(); ++boxNdx) {
- pw.print(prefix); pw.print("StackBox #"); pw.println(boxNdx);
- mStackBoxes.get(boxNdx).dump(prefix + " ", pw);
- }
- int ndx = numTokens();
- if (ndx > 0) {
- pw.println();
- pw.println(" Application tokens in Z order:");
- getTasks();
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- AppTokenList tokens = mTaskHistory.get(taskNdx).mAppTokens;
- for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
- final AppWindowToken wtoken = tokens.get(tokenNdx);
- pw.print(" App #"); pw.print(ndx--);
- pw.print(' '); pw.print(wtoken); pw.println(":");
- wtoken.dump(pw, " ");
- }
- }
- }
- if (mExitingTokens.size() > 0) {
- pw.println();
- pw.println(" Exiting tokens:");
- for (int i=mExitingTokens.size()-1; i>=0; i--) {
- WindowToken token = mExitingTokens.get(i);
- pw.print(" Exiting #"); pw.print(i);
- pw.print(' '); pw.print(token);
- pw.println(':');
- token.dump(pw, " ");
- }
- }
- if (mExitingAppTokens.size() > 0) {
- pw.println();
- pw.println(" Exiting application tokens:");
- for (int i=mExitingAppTokens.size()-1; i>=0; i--) {
- WindowToken token = mExitingAppTokens.get(i);
- pw.print(" Exiting App #"); pw.print(i);
- pw.print(' '); pw.print(token);
- pw.println(':');
- token.dump(pw, " ");
- }
- }
- pw.println();
- }
-}
diff --git a/services/java/com/android/server/wm/StackBox.java b/services/java/com/android/server/wm/StackBox.java
deleted file mode 100644
index d351925..0000000
--- a/services/java/com/android/server/wm/StackBox.java
+++ /dev/null
@@ -1,414 +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.server.wm;
-
-import android.graphics.Rect;
-import android.util.Slog;
-
-import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
-import static com.android.server.wm.WindowManagerService.DEBUG_STACK;
-import static com.android.server.wm.WindowManagerService.TAG;
-
-import java.io.PrintWriter;
-
-public class StackBox {
- /** Used with {@link WindowManagerService#createStack}. Dependent on Configuration LTR/RTL. */
- public static final int TASK_STACK_GOES_BEFORE = 0;
- /** Used with {@link WindowManagerService#createStack}. Dependent on Configuration LTR/RTL. */
- public static final int TASK_STACK_GOES_AFTER = 1;
- /** Used with {@link WindowManagerService#createStack}. Horizontal to left of. */
- public static final int TASK_STACK_TO_LEFT_OF = 2;
- /** Used with {@link WindowManagerService#createStack}. Horizontal to right of. */
- public static final int TASK_STACK_TO_RIGHT_OF = 3;
- /** Used with {@link WindowManagerService#createStack}. Vertical: lower t/b Rect values. */
- public static final int TASK_STACK_GOES_ABOVE = 4;
- /** Used with {@link WindowManagerService#createStack}. Vertical: higher t/b Rect values. */
- public static final int TASK_STACK_GOES_BELOW = 5;
- /** Used with {@link WindowManagerService#createStack}. Put on a higher layer on display. */
- public static final int TASK_STACK_GOES_OVER = 6;
- /** Used with {@link WindowManagerService#createStack}. Put on a lower layer on display. */
- public static final int TASK_STACK_GOES_UNDER = 7;
-
- static int sCurrentBoxId = 0;
-
- /** Unique id for this box */
- final int mStackBoxId;
-
- /** The service */
- final WindowManagerService mService;
-
- /** The display this box sits in. */
- final DisplayContent mDisplayContent;
-
- /** Non-null indicates this is mFirst or mSecond of a parent StackBox. Null indicates this
- * is this entire size of mDisplayContent. */
- StackBox mParent;
-
- /** First child, this is null exactly when mStack is non-null. */
- StackBox mFirst;
-
- /** Second child, this is null exactly when mStack is non-null. */
- StackBox mSecond;
-
- /** Stack of Tasks, this is null exactly when mFirst and mSecond are non-null. */
- TaskStack mStack;
-
- /** Content limits relative to the DisplayContent this sits in. */
- Rect mBounds = new Rect();
-
- /** Relative orientation of mFirst and mSecond. */
- boolean mVertical;
-
- /** Fraction of mBounds to devote to mFirst, remainder goes to mSecond */
- float mWeight;
-
- /** Dirty flag. Something inside this or some descendant of this has changed. */
- boolean layoutNeeded;
-
- /** True if this StackBox sits below the Status Bar. */
- boolean mUnderStatusBar;
-
- /** Used to keep from reallocating a temporary Rect for propagating bounds to child boxes */
- Rect mTmpRect = new Rect();
-
- StackBox(WindowManagerService service, DisplayContent displayContent, StackBox parent) {
- synchronized (StackBox.class) {
- mStackBoxId = sCurrentBoxId++;
- }
-
- mService = service;
- mDisplayContent = displayContent;
- mParent = parent;
- }
-
- /** Propagate #layoutNeeded bottom up. */
- void makeDirty() {
- layoutNeeded = true;
- if (mParent != null) {
- mParent.makeDirty();
- }
- }
-
- /**
- * Determine if a particular StackBox is this one or a descendant of this one.
- * @param stackBoxId The StackBox being searched for.
- * @return true if the specified StackBox matches this or one of its descendants.
- */
- boolean contains(int stackBoxId) {
- return mStackBoxId == stackBoxId ||
- (mStack == null && (mFirst.contains(stackBoxId) || mSecond.contains(stackBoxId)));
- }
-
- /**
- * Return the stackId of the stack that intersects the passed point.
- * @param x coordinate of point.
- * @param y coordinate of point.
- * @return -1 if point is outside of mBounds, otherwise the stackId of the containing stack.
- */
- int stackIdFromPoint(int x, int y) {
- if (!mBounds.contains(x, y)) {
- return -1;
- }
- if (mStack != null) {
- return mStack.mStackId;
- }
- int stackId = mFirst.stackIdFromPoint(x, y);
- if (stackId >= 0) {
- return stackId;
- }
- return mSecond.stackIdFromPoint(x, y);
- }
-
- /** Determine if this StackBox is the first child or second child.
- * @return true if this is the first child.
- */
- boolean isFirstChild() {
- return mParent != null && mParent.mFirst == this;
- }
-
- /** Returns the bounds of the specified TaskStack if it is contained in this StackBox.
- * @param stackId the TaskStack to find the bounds of.
- * @return a new Rect with the bounds of stackId if it is within this StackBox, null otherwise.
- */
- Rect getStackBounds(int stackId) {
- if (mStack != null) {
- return mStack.mStackId == stackId ? new Rect(mBounds) : null;
- }
- Rect bounds = mFirst.getStackBounds(stackId);
- if (bounds != null) {
- return bounds;
- }
- return mSecond.getStackBounds(stackId);
- }
-
- /**
- * Create a new TaskStack relative to a specified one by splitting the StackBox containing
- * the specified TaskStack into two children. The size and position each of the new StackBoxes
- * is determined by the passed parameters.
- * @param stackId The id of the new TaskStack to create.
- * @param relativeStackBoxId The id of the StackBox to place the new TaskStack next to.
- * @param position One of the static TASK_STACK_GOES_xxx positions defined in this class.
- * @param weight The percentage size of the parent StackBox to devote to the new TaskStack.
- * @return The new TaskStack.
- */
- TaskStack split(int stackId, int relativeStackBoxId, int position, float weight) {
- if (mStackBoxId != relativeStackBoxId) {
- // This is not the targeted StackBox.
- if (mStack != null) {
- return null;
- }
- // Propagate the split to see if the targeted StackBox is in either sub box.
- TaskStack stack = mFirst.split(stackId, relativeStackBoxId, position, weight);
- if (stack != null) {
- return stack;
- }
- return mSecond.split(stackId, relativeStackBoxId, position, weight);
- }
-
- // Found it!
- TaskStack stack = new TaskStack(mService, stackId, mDisplayContent);
- TaskStack firstStack;
- TaskStack secondStack;
- if (position == TASK_STACK_GOES_BEFORE) {
- // TODO: Test Configuration here for LTR/RTL.
- position = TASK_STACK_TO_LEFT_OF;
- } else if (position == TASK_STACK_GOES_AFTER) {
- // TODO: Test Configuration here for LTR/RTL.
- position = TASK_STACK_TO_RIGHT_OF;
- }
- switch (position) {
- default:
- case TASK_STACK_TO_LEFT_OF:
- case TASK_STACK_TO_RIGHT_OF:
- mVertical = false;
- if (position == TASK_STACK_TO_LEFT_OF) {
- mWeight = weight;
- firstStack = stack;
- secondStack = mStack;
- } else {
- mWeight = 1.0f - weight;
- firstStack = mStack;
- secondStack = stack;
- }
- break;
- case TASK_STACK_GOES_ABOVE:
- case TASK_STACK_GOES_BELOW:
- mVertical = true;
- if (position == TASK_STACK_GOES_ABOVE) {
- mWeight = weight;
- firstStack = stack;
- secondStack = mStack;
- } else {
- mWeight = 1.0f - weight;
- firstStack = mStack;
- secondStack = stack;
- }
- break;
- }
-
- mFirst = new StackBox(mService, mDisplayContent, this);
- firstStack.mStackBox = mFirst;
- mFirst.mStack = firstStack;
-
- mSecond = new StackBox(mService, mDisplayContent, this);
- secondStack.mStackBox = mSecond;
- mSecond.mStack = secondStack;
-
- mStack = null;
- return stack;
- }
-
- /** Return the stackId of the first mFirst StackBox with a non-null mStack */
- int getStackId() {
- if (mStack != null) {
- return mStack.mStackId;
- }
- return mFirst.getStackId();
- }
-
- /** Remove this box and propagate its sibling's content up to their parent.
- * @return The first stackId of the resulting StackBox. */
- int remove() {
- mDisplayContent.layoutNeeded = true;
-
- if (mParent == null) {
- // This is the top-plane stack.
- if (DEBUG_STACK) Slog.i(TAG, "StackBox.remove: removing top plane.");
- mDisplayContent.removeStackBox(this);
- return HOME_STACK_ID;
- }
-
- StackBox sibling = isFirstChild() ? mParent.mSecond : mParent.mFirst;
- StackBox grandparent = mParent.mParent;
- sibling.mParent = grandparent;
- if (grandparent == null) {
- // mParent is a top-plane stack. Now sibling will be.
- if (DEBUG_STACK) Slog.i(TAG, "StackBox.remove: grandparent null");
- mDisplayContent.removeStackBox(mParent);
- mDisplayContent.addStackBox(sibling, true);
- } else {
- if (DEBUG_STACK) Slog.i(TAG, "StackBox.remove: grandparent getting sibling");
- if (mParent.isFirstChild()) {
- grandparent.mFirst = sibling;
- } else {
- grandparent.mSecond = sibling;
- }
- }
- return sibling.getStackId();
- }
-
- boolean resize(int stackBoxId, float weight) {
- if (mStackBoxId != stackBoxId) {
- return mStack == null &&
- (mFirst.resize(stackBoxId, weight) || mSecond.resize(stackBoxId, weight));
- }
- // Don't change weight on topmost stack.
- if (mParent != null) {
- mParent.mWeight = isFirstChild() ? weight : 1.0f - weight;
- }
- return true;
- }
-
- /** If this is a terminal StackBox (contains a TaskStack) set the bounds.
- * @param bounds The rectangle to set the bounds to.
- * @param underStatusBar True if the StackBox is directly below the Status Bar.
- * @return True if the bounds changed, false otherwise. */
- boolean setStackBoxSizes(Rect bounds, boolean underStatusBar) {
- boolean change = false;
- if (mUnderStatusBar != underStatusBar) {
- change = true;
- mUnderStatusBar = underStatusBar;
- }
- if (mStack != null) {
- change |= !mBounds.equals(bounds);
- if (change) {
- mBounds.set(bounds);
- mStack.setBounds(bounds, underStatusBar);
- }
- } else {
- mTmpRect.set(bounds);
- if (mVertical) {
- final int height = bounds.height();
- int firstHeight = (int)(height * mWeight);
- mTmpRect.bottom = bounds.top + firstHeight;
- change |= mFirst.setStackBoxSizes(mTmpRect, underStatusBar);
- mTmpRect.top = mTmpRect.bottom;
- mTmpRect.bottom = bounds.top + height;
- change |= mSecond.setStackBoxSizes(mTmpRect, false);
- } else {
- final int width = bounds.width();
- int firstWidth = (int)(width * mWeight);
- mTmpRect.right = bounds.left + firstWidth;
- change |= mFirst.setStackBoxSizes(mTmpRect, underStatusBar);
- mTmpRect.left = mTmpRect.right;
- mTmpRect.right = bounds.left + width;
- change |= mSecond.setStackBoxSizes(mTmpRect, underStatusBar);
- }
- }
- return change;
- }
-
- void resetAnimationBackgroundAnimator() {
- if (mStack != null) {
- mStack.resetAnimationBackgroundAnimator();
- return;
- }
- mFirst.resetAnimationBackgroundAnimator();
- mSecond.resetAnimationBackgroundAnimator();
- }
-
- boolean animateDimLayers() {
- if (mStack != null) {
- return mStack.animateDimLayers();
- }
- boolean result = mFirst.animateDimLayers();
- result |= mSecond.animateDimLayers();
- return result;
- }
-
- void resetDimming() {
- if (mStack != null) {
- mStack.resetDimmingTag();
- return;
- }
- mFirst.resetDimming();
- mSecond.resetDimming();
- }
-
- boolean isDimming() {
- if (mStack != null) {
- return mStack.isDimming();
- }
- boolean result = mFirst.isDimming();
- result |= mSecond.isDimming();
- return result;
- }
-
- void stopDimmingIfNeeded() {
- if (mStack != null) {
- mStack.stopDimmingIfNeeded();
- return;
- }
- mFirst.stopDimmingIfNeeded();
- mSecond.stopDimmingIfNeeded();
- }
-
- void switchUserStacks(int userId) {
- if (mStack != null) {
- mStack.switchUser(userId);
- return;
- }
- mFirst.switchUserStacks(userId);
- mSecond.switchUserStacks(userId);
- }
-
- void close() {
- if (mStack != null) {
- mStack.mDimLayer.mDimSurface.destroy();
- mStack.mAnimationBackgroundSurface.mDimSurface.destroy();
- return;
- }
- mFirst.close();
- mSecond.close();
- }
-
- public void dump(String prefix, PrintWriter pw) {
- pw.print(prefix); pw.print("mParent="); pw.println(mParent);
- pw.print(prefix); pw.print("mBounds="); pw.print(mBounds.toShortString());
- pw.print(" mVertical="); pw.print(mVertical);
- pw.print(" layoutNeeded="); pw.println(layoutNeeded);
- if (mFirst != null) {
- pw.print(prefix); pw.print("mFirst="); pw.println(System.identityHashCode(mFirst));
- mFirst.dump(prefix + " ", pw);
- pw.print(prefix); pw.print("mSecond="); pw.println(System.identityHashCode(mSecond));
- mSecond.dump(prefix + " ", pw);
- } else {
- pw.print(prefix); pw.print("mStack="); pw.println(mStack);
- mStack.dump(prefix + " ", pw);
- }
- }
-
- @Override
- public String toString() {
- if (mStack != null) {
- return "Box{" + hashCode() + " stack=" + mStack.mStackId + "}";
- }
- return "Box{" + hashCode() + " parent=" + System.identityHashCode(mParent)
- + " first=" + System.identityHashCode(mFirst)
- + " second=" + System.identityHashCode(mSecond) + "}";
- }
-}
diff --git a/services/jni/Android.mk b/services/jni/Android.mk
deleted file mode 100644
index 98e9b30..0000000
--- a/services/jni/Android.mk
+++ /dev/null
@@ -1,63 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- com_android_server_AlarmManagerService.cpp \
- com_android_server_AssetAtlasService.cpp \
- com_android_server_ConsumerIrService.cpp \
- com_android_server_input_InputApplicationHandle.cpp \
- com_android_server_input_InputManagerService.cpp \
- com_android_server_input_InputWindowHandle.cpp \
- com_android_server_LightsService.cpp \
- com_android_server_power_PowerManagerService.cpp \
- com_android_server_SerialService.cpp \
- com_android_server_SystemServer.cpp \
- com_android_server_UsbDeviceManager.cpp \
- com_android_server_UsbHostManager.cpp \
- com_android_server_VibratorService.cpp \
- com_android_server_location_GpsLocationProvider.cpp \
- com_android_server_location_FlpHardwareProvider.cpp \
- com_android_server_connectivity_Vpn.cpp \
- onload.cpp
-
-LOCAL_C_INCLUDES += \
- $(JNI_H_INCLUDE) \
- frameworks/base/services \
- frameworks/base/core/jni \
- frameworks/native/services \
- external/skia/include/core \
- libcore/include \
- libcore/include/libsuspend \
- $(call include-path-for, libhardware)/hardware \
- $(call include-path-for, libhardware_legacy)/hardware_legacy \
-
-LOCAL_SHARED_LIBRARIES := \
- libandroid_runtime \
- libandroidfw \
- libbinder \
- libcutils \
- liblog \
- libhardware \
- libhardware_legacy \
- libnativehelper \
- libutils \
- libui \
- libinput \
- libinputservice \
- libsensorservice \
- libskia \
- libgui \
- libusbhost \
- libsuspend \
- libEGL \
- libGLESv2
-
-LOCAL_CFLAGS += -DEGL_EGLEXT_PROTOTYPES -DGL_GLEXT_PROTOTYPES
-
-ifeq ($(WITH_MALLOC_LEAK_CHECK),true)
- LOCAL_CFLAGS += -DMALLOC_LEAK_CHECK
-endif
-
-LOCAL_MODULE:= libandroid_servers
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/services/print/java/com/android/server/print/PrintManagerService.java b/services/print/java/com/android/server/print/PrintManagerService.java
new file mode 100644
index 0000000..852736b
--- /dev/null
+++ b/services/print/java/com/android/server/print/PrintManagerService.java
@@ -0,0 +1,690 @@
+/*
+ * 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.server.print;
+
+import android.Manifest;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.print.IPrintDocumentAdapter;
+import android.print.IPrintJobStateChangeListener;
+import android.print.IPrintManager;
+import android.print.IPrinterDiscoveryObserver;
+import android.print.PrintAttributes;
+import android.print.PrintJobId;
+import android.print.PrintJobInfo;
+import android.print.PrinterId;
+import android.printservice.PrintServiceInfo;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.SparseArray;
+
+import com.android.internal.R;
+import com.android.internal.content.PackageMonitor;
+import com.android.internal.os.BackgroundThread;
+import com.android.server.SystemService;
+import com.android.server.devicepolicy.DevicePolicyManagerService;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * SystemService wrapper for the PrintManager implementation. Publishes
+ * Context.PRINT_SERVICE.
+ * PrintManager implementation is contained within.
+ */
+
+public final class PrintManagerService extends SystemService {
+
+ private PrintManagerImpl mPrintManagerImpl;
+
+ @Override
+ public void onCreate(Context context) {
+ mPrintManagerImpl = new PrintManagerImpl(context);
+ }
+ @Override
+ public void onStart() {
+ publishBinderService(Context.PRINT_SERVICE, mPrintManagerImpl);
+ }
+
+ @Override
+ public void onBootPhase(int phase) {
+ if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
+ mPrintManagerImpl.systemRunning();
+ }
+ }
+
+ class PrintManagerImpl extends IPrintManager.Stub {
+ private static final char COMPONENT_NAME_SEPARATOR = ':';
+
+ private static final String EXTRA_PRINT_SERVICE_COMPONENT_NAME =
+ "EXTRA_PRINT_SERVICE_COMPONENT_NAME";
+
+ private final Object mLock = new Object();
+
+ private final Context mContext;
+
+ private final SparseArray<UserState> mUserStates = new SparseArray<UserState>();
+
+ private int mCurrentUserId = UserHandle.USER_OWNER;
+
+ PrintManagerImpl(Context context) {
+ mContext = context;
+ registerContentObservers();
+ registerBoradcastReceivers();
+ }
+
+ public void systemRunning() {
+ BackgroundThread.getHandler().post(new Runnable() {
+ @Override
+ public void run() {
+ final UserState userState;
+ synchronized (mLock) {
+ userState = getCurrentUserStateLocked();
+ userState.updateIfNeededLocked();
+ }
+ // This is the first time we switch to this user after boot, so
+ // now is the time to remove obsolete print jobs since they
+ // are from the last boot and no application would query them.
+ userState.removeObsoletePrintJobs();
+ }
+ });
+ }
+
+ @Override
+ public Bundle print(String printJobName, IPrintDocumentAdapter adapter,
+ PrintAttributes attributes, String packageName, int appId, int userId) {
+ final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
+ final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
+ String resolvedPackageName = resolveCallingPackageNameEnforcingSecurity(packageName);
+ final UserState userState;
+ synchronized (mLock) {
+ userState = getOrCreateUserStateLocked(resolvedUserId);
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ return userState.print(printJobName, adapter, attributes,
+ resolvedPackageName, resolvedAppId);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public List<PrintJobInfo> getPrintJobInfos(int appId, int userId) {
+ final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
+ final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
+ final UserState userState;
+ synchronized (mLock) {
+ userState = getOrCreateUserStateLocked(resolvedUserId);
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ return userState.getPrintJobInfos(resolvedAppId);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public PrintJobInfo getPrintJobInfo(PrintJobId printJobId, int appId, int userId) {
+ final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
+ final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
+ final UserState userState;
+ synchronized (mLock) {
+ userState = getOrCreateUserStateLocked(resolvedUserId);
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ return userState.getPrintJobInfo(printJobId, resolvedAppId);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void cancelPrintJob(PrintJobId printJobId, int appId, int userId) {
+ final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
+ final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
+ final UserState userState;
+ synchronized (mLock) {
+ userState = getOrCreateUserStateLocked(resolvedUserId);
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ userState.cancelPrintJob(printJobId, resolvedAppId);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void restartPrintJob(PrintJobId printJobId, int appId, int userId) {
+ final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
+ final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
+ final UserState userState;
+ synchronized (mLock) {
+ userState = getOrCreateUserStateLocked(resolvedUserId);
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ userState.restartPrintJob(printJobId, resolvedAppId);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public List<PrintServiceInfo> getEnabledPrintServices(int userId) {
+ final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
+ final UserState userState;
+ synchronized (mLock) {
+ userState = getOrCreateUserStateLocked(resolvedUserId);
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ return userState.getEnabledPrintServices();
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public List<PrintServiceInfo> getInstalledPrintServices(int userId) {
+ final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
+ final UserState userState;
+ synchronized (mLock) {
+ userState = getOrCreateUserStateLocked(resolvedUserId);
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ return userState.getInstalledPrintServices();
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void createPrinterDiscoverySession(IPrinterDiscoveryObserver observer,
+ int userId) {
+ final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
+ final UserState userState;
+ synchronized (mLock) {
+ userState = getOrCreateUserStateLocked(resolvedUserId);
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ userState.createPrinterDiscoverySession(observer);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void destroyPrinterDiscoverySession(IPrinterDiscoveryObserver observer,
+ int userId) {
+ final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
+ final UserState userState;
+ synchronized (mLock) {
+ userState = getOrCreateUserStateLocked(resolvedUserId);
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ userState.destroyPrinterDiscoverySession(observer);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void startPrinterDiscovery(IPrinterDiscoveryObserver observer,
+ List<PrinterId> priorityList, int userId) {
+ final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
+ final UserState userState;
+ synchronized (mLock) {
+ userState = getOrCreateUserStateLocked(resolvedUserId);
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ userState.startPrinterDiscovery(observer, priorityList);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void stopPrinterDiscovery(IPrinterDiscoveryObserver observer, int userId) {
+ final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
+ final UserState userState;
+ synchronized (mLock) {
+ userState = getOrCreateUserStateLocked(resolvedUserId);
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ userState.stopPrinterDiscovery(observer);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void validatePrinters(List<PrinterId> printerIds, int userId) {
+ final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
+ final UserState userState;
+ synchronized (mLock) {
+ userState = getOrCreateUserStateLocked(resolvedUserId);
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ userState.validatePrinters(printerIds);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void startPrinterStateTracking(PrinterId printerId, int userId) {
+ final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
+ final UserState userState;
+ synchronized (mLock) {
+ userState = getOrCreateUserStateLocked(resolvedUserId);
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ userState.startPrinterStateTracking(printerId);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void stopPrinterStateTracking(PrinterId printerId, int userId) {
+ final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
+ final UserState userState;
+ synchronized (mLock) {
+ userState = getOrCreateUserStateLocked(resolvedUserId);
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ userState.stopPrinterStateTracking(printerId);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void addPrintJobStateChangeListener(IPrintJobStateChangeListener listener,
+ int appId, int userId) throws RemoteException {
+ final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
+ final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
+ final UserState userState;
+ synchronized (mLock) {
+ userState = getOrCreateUserStateLocked(resolvedUserId);
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ userState.addPrintJobStateChangeListener(listener, resolvedAppId);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void removePrintJobStateChangeListener(IPrintJobStateChangeListener listener,
+ int userId) {
+ final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
+ final UserState userState;
+ synchronized (mLock) {
+ userState = getOrCreateUserStateLocked(resolvedUserId);
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ userState.removePrintJobStateChangeListener(listener);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
+ != PackageManager.PERMISSION_GRANTED) {
+ pw.println("Permission Denial: can't dump PrintManager from from pid="
+ + Binder.getCallingPid()
+ + ", uid=" + Binder.getCallingUid());
+ return;
+ }
+
+ synchronized (mLock) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ pw.println("PRINT MANAGER STATE (dumpsys print)");
+ final int userStateCount = mUserStates.size();
+ for (int i = 0; i < userStateCount; i++) {
+ UserState userState = mUserStates.valueAt(i);
+ userState.dump(fd, pw, "");
+ pw.println();
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ }
+
+ private void registerContentObservers() {
+ final Uri enabledPrintServicesUri = Settings.Secure.getUriFor(
+ Settings.Secure.ENABLED_PRINT_SERVICES);
+
+ ContentObserver observer = new ContentObserver(BackgroundThread.getHandler()) {
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ if (enabledPrintServicesUri.equals(uri)) {
+ synchronized (mLock) {
+ UserState userState = getCurrentUserStateLocked();
+ userState.updateIfNeededLocked();
+ }
+ }
+ }
+ };
+
+ mContext.getContentResolver().registerContentObserver(enabledPrintServicesUri,
+ false, observer, UserHandle.USER_ALL);
+ }
+
+ private void registerBoradcastReceivers() {
+ PackageMonitor monitor = new PackageMonitor() {
+ @Override
+ public boolean onPackageChanged(String packageName, int uid, String[] components) {
+ synchronized (mLock) {
+ UserState userState = getOrCreateUserStateLocked(getChangingUserId());
+ Iterator<ComponentName> iterator = userState.getEnabledServices()
+ .iterator();
+ while (iterator.hasNext()) {
+ ComponentName componentName = iterator.next();
+ if (packageName.equals(componentName.getPackageName())) {
+ userState.updateIfNeededLocked();
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void onPackageRemoved(String packageName, int uid) {
+ synchronized (mLock) {
+ UserState userState = getOrCreateUserStateLocked(getChangingUserId());
+ Iterator<ComponentName> iterator = userState.getEnabledServices()
+ .iterator();
+ while (iterator.hasNext()) {
+ ComponentName componentName = iterator.next();
+ if (packageName.equals(componentName.getPackageName())) {
+ iterator.remove();
+ persistComponentNamesToSettingLocked(
+ Settings.Secure.ENABLED_PRINT_SERVICES,
+ userState.getEnabledServices(), getChangingUserId());
+ userState.updateIfNeededLocked();
+ return;
+ }
+ }
+ }
+ }
+
+ @Override
+ public boolean onHandleForceStop(Intent intent, String[] stoppedPackages,
+ int uid, boolean doit) {
+ synchronized (mLock) {
+ UserState userState = getOrCreateUserStateLocked(getChangingUserId());
+ boolean stoppedSomePackages = false;
+ Iterator<ComponentName> iterator = userState.getEnabledServices()
+ .iterator();
+ while (iterator.hasNext()) {
+ ComponentName componentName = iterator.next();
+ String componentPackage = componentName.getPackageName();
+ for (String stoppedPackage : stoppedPackages) {
+ if (componentPackage.equals(stoppedPackage)) {
+ if (!doit) {
+ return true;
+ }
+ stoppedSomePackages = true;
+ break;
+ }
+ }
+ }
+ if (stoppedSomePackages) {
+ userState.updateIfNeededLocked();
+ }
+ return false;
+ }
+ }
+
+ @Override
+ public void onPackageAdded(String packageName, int uid) {
+ Intent intent = new Intent(android.printservice.PrintService.SERVICE_INTERFACE);
+ intent.setPackage(packageName);
+
+ List<ResolveInfo> installedServices = mContext.getPackageManager()
+ .queryIntentServicesAsUser(intent, PackageManager.GET_SERVICES,
+ getChangingUserId());
+
+ if (installedServices == null) {
+ return;
+ }
+
+ final int installedServiceCount = installedServices.size();
+ for (int i = 0; i < installedServiceCount; i++) {
+ ServiceInfo serviceInfo = installedServices.get(i).serviceInfo;
+ ComponentName component = new ComponentName(serviceInfo.packageName,
+ serviceInfo.name);
+ String label = serviceInfo.loadLabel(mContext.getPackageManager())
+ .toString();
+ showEnableInstalledPrintServiceNotification(component, label,
+ getChangingUserId());
+ }
+ }
+
+ private void persistComponentNamesToSettingLocked(String settingName,
+ Set<ComponentName> componentNames, int userId) {
+ StringBuilder builder = new StringBuilder();
+ for (ComponentName componentName : componentNames) {
+ if (builder.length() > 0) {
+ builder.append(COMPONENT_NAME_SEPARATOR);
+ }
+ builder.append(componentName.flattenToShortString());
+ }
+ Settings.Secure.putStringForUser(mContext.getContentResolver(),
+ settingName, builder.toString(), userId);
+ }
+ };
+
+ // package changes
+ monitor.register(mContext, BackgroundThread.getHandler().getLooper(),
+ UserHandle.ALL, true);
+
+ // user changes
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
+ intentFilter.addAction(Intent.ACTION_USER_REMOVED);
+
+ mContext.registerReceiverAsUser(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (Intent.ACTION_USER_SWITCHED.equals(action)) {
+ switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
+ } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
+ removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
+ }
+ }
+ }, UserHandle.ALL, intentFilter, null, BackgroundThread.getHandler());
+ }
+
+ private UserState getCurrentUserStateLocked() {
+ return getOrCreateUserStateLocked(mCurrentUserId);
+ }
+
+ private UserState getOrCreateUserStateLocked(int userId) {
+ UserState userState = mUserStates.get(userId);
+ if (userState == null) {
+ userState = new UserState(mContext, userId, mLock);
+ mUserStates.put(userId, userState);
+ }
+ return userState;
+ }
+
+ private void switchUser(int newUserId) {
+ UserState userState;
+ synchronized (mLock) {
+ if (newUserId == mCurrentUserId) {
+ return;
+ }
+ mCurrentUserId = newUserId;
+ userState = mUserStates.get(mCurrentUserId);
+ if (userState == null) {
+ userState = getCurrentUserStateLocked();
+ userState.updateIfNeededLocked();
+ } else {
+ userState.updateIfNeededLocked();
+ }
+ }
+ // This is the first time we switch to this user after boot, so
+ // now is the time to remove obsolete print jobs since they
+ // are from the last boot and no application would query them.
+ userState.removeObsoletePrintJobs();
+ }
+
+ private void removeUser(int removedUserId) {
+ synchronized (mLock) {
+ UserState userState = mUserStates.get(removedUserId);
+ if (userState != null) {
+ userState.destroyLocked();
+ mUserStates.remove(removedUserId);
+ }
+ }
+ }
+
+ private int resolveCallingAppEnforcingPermissions(int appId) {
+ final int callingUid = Binder.getCallingUid();
+ if (callingUid == 0 || callingUid == Process.SYSTEM_UID
+ || callingUid == Process.SHELL_UID) {
+ return appId;
+ }
+ final int callingAppId = UserHandle.getAppId(callingUid);
+ if (appId == callingAppId) {
+ return appId;
+ }
+ if (mContext.checkCallingPermission(
+ "com.android.printspooler.permission.ACCESS_ALL_PRINT_JOBS")
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Call from app " + callingAppId + " as app "
+ + appId + " without com.android.printspooler.permission"
+ + ".ACCESS_ALL_PRINT_JOBS");
+ }
+ return appId;
+ }
+
+ private int resolveCallingUserEnforcingPermissions(int userId) {
+ final int callingUid = Binder.getCallingUid();
+ if (callingUid == 0 || callingUid == Process.SYSTEM_UID
+ || callingUid == Process.SHELL_UID) {
+ return userId;
+ }
+ final int callingUserId = UserHandle.getUserId(callingUid);
+ if (callingUserId == userId) {
+ return userId;
+ }
+ if (mContext.checkCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL)
+ != PackageManager.PERMISSION_GRANTED
+ || mContext.checkCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS)
+ != PackageManager.PERMISSION_GRANTED) {
+ if (userId == UserHandle.USER_CURRENT_OR_SELF) {
+ return callingUserId;
+ }
+ throw new SecurityException("Call from user " + callingUserId + " as user "
+ + userId + " without permission INTERACT_ACROSS_USERS or "
+ + "INTERACT_ACROSS_USERS_FULL not allowed.");
+ }
+ if (userId == UserHandle.USER_CURRENT || userId == UserHandle.USER_CURRENT_OR_SELF) {
+ return mCurrentUserId;
+ }
+ throw new IllegalArgumentException("Calling user can be changed to only "
+ + "UserHandle.USER_CURRENT or UserHandle.USER_CURRENT_OR_SELF.");
+ }
+
+ private String resolveCallingPackageNameEnforcingSecurity(String packageName) {
+ if (TextUtils.isEmpty(packageName)) {
+ return null;
+ }
+ String[] packages = mContext.getPackageManager().getPackagesForUid(
+ Binder.getCallingUid());
+ final int packageCount = packages.length;
+ for (int i = 0; i < packageCount; i++) {
+ if (packageName.equals(packages[i])) {
+ return packageName;
+ }
+ }
+ return null;
+ }
+
+ private void showEnableInstalledPrintServiceNotification(ComponentName component,
+ String label, int userId) {
+ UserHandle userHandle = new UserHandle(userId);
+
+ Intent intent = new Intent(Settings.ACTION_PRINT_SETTINGS);
+ intent.putExtra(EXTRA_PRINT_SERVICE_COMPONENT_NAME, component.flattenToString());
+
+ PendingIntent pendingIntent = PendingIntent.getActivityAsUser(mContext, 0, intent,
+ PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_CANCEL_CURRENT, null,
+ userHandle);
+
+ Notification.Builder builder = new Notification.Builder(mContext)
+ .setSmallIcon(R.drawable.ic_print)
+ .setContentTitle(mContext.getString(R.string.print_service_installed_title,
+ label))
+ .setContentText(mContext.getString(R.string.print_service_installed_message))
+ .setContentIntent(pendingIntent)
+ .setWhen(System.currentTimeMillis())
+ .setAutoCancel(true)
+ .setShowWhen(true);
+
+ NotificationManager notificationManager = (NotificationManager) mContext
+ .getSystemService(Context.NOTIFICATION_SERVICE);
+
+ String notificationTag = getClass().getName() + ":" + component.flattenToString();
+ notificationManager.notifyAsUser(notificationTag, 0, builder.build(),
+ userHandle);
+ }
+ }
+}
diff --git a/services/java/com/android/server/print/RemotePrintService.java b/services/print/java/com/android/server/print/RemotePrintService.java
similarity index 100%
rename from services/java/com/android/server/print/RemotePrintService.java
rename to services/print/java/com/android/server/print/RemotePrintService.java
diff --git a/services/java/com/android/server/print/RemotePrintSpooler.java b/services/print/java/com/android/server/print/RemotePrintSpooler.java
similarity index 100%
rename from services/java/com/android/server/print/RemotePrintSpooler.java
rename to services/print/java/com/android/server/print/RemotePrintSpooler.java
diff --git a/services/java/com/android/server/print/UserState.java b/services/print/java/com/android/server/print/UserState.java
similarity index 100%
rename from services/java/com/android/server/print/UserState.java
rename to services/print/java/com/android/server/print/UserState.java
diff --git a/services/print/java/service.mk b/services/print/java/service.mk
new file mode 100644
index 0000000..cba3612
--- /dev/null
+++ b/services/print/java/service.mk
@@ -0,0 +1,11 @@
+# Include only if the service is required
+ifneq ($(findstring print,$(REQUIRED_SERVICES)),)
+
+SUB_DIR := print/java
+
+LOCAL_SRC_FILES += \
+ $(call all-java-files-under,$(SUB_DIR))
+
+#DEFINED_SERVICES += com.android.server.print.PrintManagerService
+
+endif
diff --git a/services/tests/Android.mk b/services/tests/Android.mk
new file mode 100644
index 0000000..40369ee
--- /dev/null
+++ b/services/tests/Android.mk
@@ -0,0 +1,3 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(call all-makefiles-under, $(LOCAL_PATH))