~ci-train-bot/usensord/usensord-ubuntu-vivid-landing-017

« back to all changes in this revision

Viewing changes to haptic/haptic.go

  • Committer: Bileto Bot
  • Date: 2016-07-29 01:03:15 UTC
  • mfrom: (25.1.8 usensord)
  • Revision ID: ci-train-bot@canonical.com-20160729010315-djef4g4z94wrevur
Fix lp:1433590.
Expose OtherVibrate property for system settings to change(Enable/Disable).
The value of the property is saved in file(.config/usensord/prop.json) in
order to be kept after reboot and restored after factory reset.
Identify if the peer is OSK and vibrate for it always. If not, check
the OtherVibrate property, if it is 1, then do vibration. If it is 0,
don't do vibration.

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
package haptic
23
23
 
24
24
import (
 
25
        "encoding/json"
25
26
        "fmt"
26
27
        "log"
 
28
        "io/ioutil"
27
29
        "os"
 
30
        "os/user"
 
31
        "path"
 
32
        "strconv"
 
33
        "strings"
28
34
        "sync"
29
35
        "time"
30
36
 
31
37
        "launchpad.net/go-dbus/v1"
32
38
)
 
39
// #cgo CFLAGS: -I/usr/include
 
40
// #cgo linux,amd64 LDFLAGS: -L/usr/lib/x86_64-linux-gnu -lapparmor
 
41
// #cgo linux,arm LDFLAGS: -L/usr/lib/arm-linux-gnueabihf -lapparmor
 
42
// #cgo linux,arm64 LDFLAGS: -L/usr/lib/aarch64-linux-gnu -lapparmor
 
43
//#include <sys/apparmor.h>
 
44
//#include <errno.h>
 
45
import "C"
 
46
 
 
47
type Prop struct {
 
48
    OtherVibrate uint32
 
49
}
33
50
 
34
51
var (
35
52
        conn   *dbus.Connection
40
57
        mutex  *sync.Mutex
41
58
        cookie string
42
59
        timer  *time.Timer
 
60
        pvalue uint32
 
61
        configFile string
43
62
)
44
63
 
45
64
const (
46
65
        HAPTIC_DBUS_IFACE = "com.canonical.usensord.haptic"
47
66
        HAPTIC_DEVICE     = "/sys/class/timed_output/vibrator/enable"
 
67
        PROP_DBUS_IFACE = "org.freedesktop.DBus.Properties"
 
68
        OSK_PROCESS_NAME = "/usr/bin/maliit-server"
 
69
        UNCONFINED_PROFILE = "unconfined"
48
70
)
49
71
 
50
72
func watchDBusMethodCalls(msgChan <-chan *dbus.Message) {
51
73
        for msg := range msgChan {
 
74
                logger.Println("msg sender", msg.Sender)
52
75
                var reply *dbus.Message
53
76
 
54
77
                if msg.Interface == HAPTIC_DBUS_IFACE {
55
78
                        reply = handleHapticInterface(msg)
56
 
                } else {
 
79
                } else if msg.Interface == PROP_DBUS_IFACE {
 
80
                        reply = handlePropInterface(msg)
 
81
                } else {
57
82
                        reply = dbus.NewErrorMessage(
58
83
                                msg,
59
84
                                "org.freedesktop.DBus.Error.UnknownInterface",
66
91
        }
67
92
}
68
93
 
 
94
func handlePropInterface(msg *dbus.Message) (reply *dbus.Message) {
 
95
        switch msg.Member {
 
96
        case "Get":
 
97
                var iname, pname string
 
98
                msg.Args(&iname, &pname)
 
99
                if iname == HAPTIC_DBUS_IFACE && pname == "OtherVibrate" {
 
100
                        reply = dbus.NewMethodReturnMessage(msg)
 
101
                        reply.AppendArgs(dbus.Variant{uint32(pvalue)})
 
102
                } else {
 
103
                        reply = dbus.NewErrorMessage(msg, "com.canonical.usensord.Error", "interface or property not correct")
 
104
                }
 
105
        case "GetAll":
 
106
                var iname string
 
107
                msg.Args(&iname)
 
108
                if iname == HAPTIC_DBUS_IFACE {
 
109
                        reply = dbus.NewMethodReturnMessage(msg)                        
 
110
                        reply.AppendArgs(dbus.Variant{uint32(pvalue)})
 
111
                } else {
 
112
                        reply = dbus.NewErrorMessage(msg, "com.canonical.usensord.Error", "interface or property not correct")
 
113
                }
 
114
        case "Set":
 
115
                var iname, pname string
 
116
                msg.Args(&iname, &pname, &pvalue)
 
117
                if iname == HAPTIC_DBUS_IFACE && pname == "OtherVibrate" && (pvalue == 1 || pvalue == 0) {
 
118
                        //save the property value
 
119
                        prop := Prop{OtherVibrate: pvalue,}
 
120
                        propJson, _ := json.Marshal(prop)
 
121
                        errwrite := ioutil.WriteFile(configFile, propJson, 0644)
 
122
                        if errwrite != nil {
 
123
                            logger.Println("WriteFile error:", errwrite)
 
124
                        }
 
125
 
 
126
                        //reply = dbus.NewSignalMessage("/com/canonical/usensord/haptic", HAPTIC_DBUS_IFACE, "Set")
 
127
                        reply = dbus.NewMethodReturnMessage(msg)
 
128
                        reply.AppendArgs(dbus.Variant{uint32(pvalue)})
 
129
                        logger.Println("Set property to be ", pvalue)
 
130
                } else {
 
131
                        reply = dbus.NewErrorMessage(msg, "com.canonical.usensord.Error", "interface or property not correct")
 
132
                }
 
133
        default:
 
134
                logger.Println("Received unknown method call on", msg.Interface, msg.Member)
 
135
                reply = dbus.NewErrorMessage(msg, "org.freedesktop.DBus.Error.UnknownMethod", "Unknown method")
 
136
        }
 
137
        return reply
 
138
}
 
139
 
69
140
func handleHapticInterface(msg *dbus.Message) (reply *dbus.Message) {
 
141
        messageBus := conn.Object("org.freedesktop.DBus", "/org/freedesktop/DBus")
 
142
        processreply, err := messageBus.Call("org.freedesktop.DBus", "GetConnectionCredentials", msg.Sender)
 
143
        if err != nil {
 
144
                reply = dbus.NewErrorMessage(msg, "com.canonical.usensord.Error", err.Error())
 
145
                return reply
 
146
        }
 
147
        var credentials map[string]dbus.Variant
 
148
        if err := processreply.Args(&credentials); err != nil {
 
149
                reply = dbus.NewErrorMessage(msg, "com.canonical.usensord.Error", err.Error())
 
150
                return reply
 
151
        }
 
152
        pid := credentials["ProcessID"].Value.(uint32)
 
153
        logger.Printf("caller process id: %d", pid)
 
154
        var profile string
 
155
        ret, error := C.aa_is_enabled()
 
156
        if ret == 1 {
 
157
                 logger.Println("aa_is_enabled")
 
158
                 label := credentials["LinuxSecurityLabel"].Value.([]interface{})
 
159
                 var bb []uint8
 
160
                 for _, f := range label {
 
161
                         bb = append(bb, f.(uint8))
 
162
                 }
 
163
                 profile = strings.TrimSpace(string(bb))
 
164
                 //LinuxSecurityLabel ends with null
 
165
                 profile = profile[:len(profile)-1]
 
166
                 logger.Println("caller process label:", profile)
 
167
        } else {
 
168
                logger.Println("aa_is_enabled failed:", error)
 
169
                profile = UNCONFINED_PROFILE
 
170
        }
 
171
        isOSK := false
 
172
        if profile == UNCONFINED_PROFILE {
 
173
                file := "/proc/" + strconv.FormatUint(uint64(pid), 10) + "/exe"
 
174
                _, err := os.Lstat(file)
 
175
                if err != nil {
 
176
                        logger.Println("error while calling os.Lstat", err)
 
177
                }
 
178
                exe, erreadexe := os.Readlink(file)
 
179
                if erreadexe != nil {
 
180
                        logger.Printf("fail to read %s with error:", file, erreadexe.Error())
 
181
                } else {
 
182
                        pname := strings.TrimSpace(string(exe))
 
183
                        logger.Println("process name:", pname)
 
184
                        if pname == OSK_PROCESS_NAME  {
 
185
                                isOSK = true
 
186
                                logger.Println("OSK calling")
 
187
                        }
 
188
                }
 
189
        }
 
190
        if !isOSK && pvalue == 0 {
 
191
                logger.Println("not vibrate since not osk and pvalue is 0")
 
192
                reply = dbus.NewMethodReturnMessage(msg)
 
193
                return reply
 
194
        }
70
195
        switch msg.Member {
71
196
        case "Vibrate":
72
197
                var duration uint32
88
213
                        reply = dbus.NewMethodReturnMessage(msg)
89
214
                }
90
215
        default:
91
 
                logger.Println("Received unkown method call on", msg.Interface, msg.Member)
 
216
                logger.Println("Received unknown method call on", msg.Interface, msg.Member)
92
217
                reply = dbus.NewErrorMessage(msg, "org.freedesktop.DBus.Error.UnknownMethod", "Unknown method")
93
218
        }
94
219
        return reply
180
305
 
181
306
        powerd = sysbus.Object("com.canonical.powerd", "/com/canonical/powerd")
182
307
        mutex = &sync.Mutex{}
 
308
        //save and load the property value
 
309
        u, err := user.Current()
 
310
        configPath := path.Join(u.HomeDir, ".config", "usensord")
 
311
        configFile = path.Join(u.HomeDir, ".config", "usensord", "prop.json")
 
312
        log.Println("configFile:", configFile)
 
313
        os.MkdirAll(configPath, 0755)
 
314
        b, errread := ioutil.ReadFile(configFile)
 
315
        if errread != nil {
 
316
                pvalue = 0
 
317
                prop := Prop{OtherVibrate: pvalue,}
 
318
                propJson, _ := json.Marshal(prop)
 
319
                errwrite := ioutil.WriteFile(configFile, propJson, 0644)
 
320
                if errwrite != nil {
 
321
                    logger.Fatal("WriteFile error:", errwrite)
 
322
                    return errwrite
 
323
                }
 
324
        } else {
 
325
                var prop Prop
 
326
                err := json.Unmarshal(b, &prop)
 
327
                if err == nil {
 
328
                        pvalue = prop.OtherVibrate
 
329
                        log.Println("pvalueb is", pvalue)
 
330
                } else {
 
331
                        log.Println("err is", err)
 
332
                        pvalue = 0
 
333
                }
 
334
        }
183
335
 
184
336
        ch := make(chan *dbus.Message)
185
337
        go watchDBusMethodCalls(ch)