245 lines
7.9 KiB
Java
245 lines
7.9 KiB
Java
/*
|
|
* Copyright 2007, The Android Open Source Project
|
|
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
|
|
*
|
|
* 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.Notification;
|
|
import android.app.NotificationManager;
|
|
import android.app.PendingIntent;
|
|
import android.content.BroadcastReceiver;
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
import android.content.IntentFilter;
|
|
import android.content.pm.PackageManager;
|
|
import android.content.res.Resources;
|
|
import android.net.Uri;
|
|
import android.os.Environment;
|
|
import android.os.IHDMIService;
|
|
import android.os.RemoteException;
|
|
import android.os.SystemProperties;
|
|
import android.os.UEventObserver;
|
|
import android.provider.Settings;
|
|
import android.text.TextUtils;
|
|
import android.util.Log;
|
|
|
|
import java.io.File;
|
|
import java.io.FileReader;
|
|
import java.util.StringTokenizer;
|
|
|
|
/**
|
|
* @hide
|
|
*/
|
|
class HDMIService extends IHDMIService.Stub {
|
|
|
|
private static final String TAG = "HDMIService";
|
|
|
|
private Context mContext;
|
|
|
|
private HDMIListener mListener;
|
|
private boolean mHDMIUserOption = false;
|
|
private int mHDMIModes[];
|
|
public final String HDMICableConnectedEvent = "HDMI_CABLE_CONNECTED";
|
|
public final String HDMICableDisconnectedEvent = "HDMI_CABLE_DISCONNECTED";
|
|
public final String HDMIONEvent = "HDMI_CONNECTED";
|
|
public final String HDMIOFFEvent = "HDMI_DISCONNECTED";
|
|
|
|
final int m640x480p60_4_3 = 1;
|
|
final int m720x480p60_4_3 = 2;
|
|
final int m720x480p60_16_9 = 3;
|
|
final int m1280x720p60_16_9 = 4;
|
|
final int m1920x1080i60_16_9 = 5;
|
|
final int m1440x480i60_4_3 = 6;
|
|
final int m1440x480i60_16_9 = 7;
|
|
final int m1920x1080p60_16_9 = 16;
|
|
final int m720x576p50_4_3 = 17;
|
|
final int m720x576p50_16_9 = 18;
|
|
final int m1280x720p50_16_9 = 19;
|
|
final int m1440x576i50_4_3 = 21;
|
|
final int m1440x576i50_16_9 = 22;
|
|
final int m1920x1080p50_16_9 = 31;
|
|
final int m1920x1080p24_16_9 = 32;
|
|
final int m1920x1080p25_16_9 = 33;
|
|
final int m1920x1080p30_16_9 = 34;
|
|
|
|
int getModeOrder(int mode)
|
|
{
|
|
switch (mode) {
|
|
default:
|
|
case m1440x480i60_4_3:
|
|
case m1440x480i60_16_9:
|
|
return 1; // 480i
|
|
case m1440x576i50_4_3:
|
|
case m1440x576i50_16_9:
|
|
return 2; // 576i
|
|
case m640x480p60_4_3:
|
|
return 3; // 480p x640
|
|
case m720x480p60_4_3:
|
|
case m720x480p60_16_9:
|
|
return 4; // 480p x720
|
|
case m720x576p50_4_3:
|
|
case m720x576p50_16_9:
|
|
return 5; // 576p
|
|
case m1920x1080i60_16_9:
|
|
return 6; // 1080i
|
|
case m1280x720p60_16_9:
|
|
case m1280x720p50_16_9:
|
|
return 7; // 720p
|
|
case m1920x1080p24_16_9:
|
|
case m1920x1080p25_16_9:
|
|
case m1920x1080p30_16_9:
|
|
case m1920x1080p50_16_9:
|
|
case m1920x1080p60_16_9:
|
|
return 8;
|
|
}
|
|
}
|
|
|
|
int getBestMode()
|
|
{
|
|
int bestOrder = 0, bestMode = m640x480p60_4_3;
|
|
for (int mode : mHDMIModes) {
|
|
int order = getModeOrder(mode);
|
|
if (order > bestOrder) {
|
|
bestOrder = order;
|
|
bestMode = mode;
|
|
}
|
|
}
|
|
return bestMode;
|
|
}
|
|
|
|
public HDMIService(Context context) {
|
|
mContext = context;
|
|
// Register a BOOT_COMPLETED handler so that we can start
|
|
// HDMIListener. We defer the startup so that we don't
|
|
// start processing events before we ought-to
|
|
mContext.registerReceiver(mBroadcastReceiver,
|
|
new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null);
|
|
mListener = new HDMIListener(this);
|
|
String hdmiUserOption = Settings.System.getString(
|
|
mContext.getContentResolver(),
|
|
"HDMI_USEROPTION");
|
|
if (hdmiUserOption != null && hdmiUserOption.equals("HDMI_ON"))
|
|
mHDMIUserOption = true;
|
|
}
|
|
|
|
BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
|
|
public void onReceive(Context context, Intent intent) {
|
|
String action = intent.getAction();
|
|
|
|
if (action.equals(Intent.ACTION_BOOT_COMPLETED)
|
|
&& (SystemProperties.getBoolean("ro.hdmi.enable", false))) {
|
|
Thread thread = new Thread(mListener, HDMIListener.class.getName());
|
|
thread.start();
|
|
}
|
|
}
|
|
};
|
|
|
|
public void shutdown() {
|
|
if (mContext.checkCallingOrSelfPermission(
|
|
android.Manifest.permission.SHUTDOWN)
|
|
!= PackageManager.PERMISSION_GRANTED) {
|
|
throw new SecurityException("Requires SHUTDOWN permission");
|
|
}
|
|
|
|
Log.e(TAG, "Shutting down");
|
|
}
|
|
|
|
public boolean isHDMIConnected() {
|
|
return mListener.isHDMIConnected();
|
|
}
|
|
|
|
public void setHDMIOutput(boolean enableHDMI) {
|
|
Settings.System.putString(mContext.getContentResolver(),
|
|
"HDMI_USEROPTION", enableHDMI ? "HDMI_ON" : "HDMI_OFF");
|
|
mHDMIUserOption = enableHDMI;
|
|
|
|
synchronized(mListener) {
|
|
if(enableHDMI == false) {
|
|
broadcastEvent(HDMIOFFEvent);
|
|
broadcastEvent(HDMICableDisconnectedEvent);
|
|
mListener.enableHDMIOutput(false);
|
|
}
|
|
mListener.setHPD(getHDMIUserOption());
|
|
}
|
|
}
|
|
|
|
public void setActionsafeWidthRatio(float asWidthRatio){
|
|
mListener.setActionsafeWidthRatio(asWidthRatio);
|
|
}
|
|
|
|
public void setActionsafeHeightRatio(float asHeightRatio){
|
|
mListener.setActionsafeHeightRatio(asHeightRatio);
|
|
}
|
|
|
|
public boolean getHDMIUserOption() {
|
|
return mHDMIUserOption;
|
|
}
|
|
|
|
public void broadcastEvent(String eventName) {
|
|
Intent intent = new Intent(eventName);
|
|
intent.addCategory(Intent.CATEGORY_DEFAULT);
|
|
mContext.sendBroadcast(intent);
|
|
Log.e(TAG, "Broadcasting ... " + eventName);
|
|
}
|
|
|
|
public void broadcastEvent(String eventName, int[] modes) {
|
|
Intent intent = new Intent(eventName);
|
|
intent.addCategory(Intent.CATEGORY_DEFAULT);
|
|
intent.putExtra("EDID", modes);
|
|
mContext.sendBroadcast(intent);
|
|
Log.e(TAG, "Broadcasting ... " + eventName + ", modes: " + modes.length);
|
|
}
|
|
|
|
public void notifyHDMIConnected(int[] modes) {
|
|
mHDMIModes = modes;
|
|
broadcastEvent(HDMICableConnectedEvent);
|
|
if(getHDMIUserOption()) {
|
|
synchronized(mListener) {
|
|
mListener.changeDisplayMode(getBestMode());
|
|
mListener.enableHDMIOutput(true);
|
|
}
|
|
if((mListener.getOnlineBroadcast())) {
|
|
Log.d(TAG, "Broadcast HDMI connected");
|
|
broadcastEvent(HDMIONEvent, mHDMIModes);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void notifyHDMIDisconnected() {
|
|
mHDMIModes = null;
|
|
broadcastEvent(HDMICableDisconnectedEvent);
|
|
if(getHDMIUserOption()) {
|
|
broadcastEvent(HDMIOFFEvent);
|
|
synchronized(mListener) {
|
|
mListener.enableHDMIOutput(false);
|
|
mListener.setHPD(getHDMIUserOption());
|
|
}
|
|
}
|
|
}
|
|
|
|
public void notifyHDMIAudioOn() {
|
|
if(getHDMIUserOption()) {
|
|
broadcastEvent(HDMIONEvent, mHDMIModes);
|
|
}
|
|
}
|
|
|
|
public void notifyHDMIAudioOff() {
|
|
if(getHDMIUserOption()) {
|
|
broadcastEvent(HDMIOFFEvent);
|
|
}
|
|
}
|
|
}
|